8

我知道这个问题已经解决了很多次——但是我的 Java/C++ 知识太薄弱了,我几乎无法理解答案:-( ...我真正想要的只是一个超级简单的例子。

在 C++ 中,我可以编写以下内容:

void func()
{
  int x = 3;
  add_one(x);
  // now x is 4.
}
void add_one(int &var)
{
  var++;
}

我现在想看到的是用java达到同样效果的最简单的方法。

4

6 回答 6

10

你不能直接。最接近的方法是将值放入对象中,然后将引用(按值,因此引用被复制)传递给方法。

void func()
{
  int x = 3;
  int[] holder = [x];
  add_one(holder);
  // now holder[0] is 4.  x is still 3.
}

// container here is a copy of the reference holder in the calling scope.
// both container and holder point to the same underlying array object
void add_one(int[] container)
{
    container[0]++;
}

这里我使用了一个数组,但是包装器可以是任何对象。

于 2012-07-11T16:42:06.857 回答
3

在 java 方法中,参数是按值传递的,不能在函数中更改。您必须将 int - 或任何其他原始类型 - 包装在 Object 或数组中。传递对象或数组作为方法参数传递可用于修改对象的引用。

Java 已经为原始类型提供了基于对象的包装器,例如Integer,但这些在设计上是不可变的。一些库提供了这些包装器的可变版本;您也可以创建自己的:

public class MutableInt
{
    private int val;

    public MutableInt(int val)
    {
        this.val = val;
    }

    public void setValue(int newVal)
    {
        this.val = newVal;
    }

    public int getValue()
    {
        return this.val;
    }
}

void func()
{
    int x = 3;
    MutableInt wrapper = new MutableInt(x);
    add_one(wrapper);
}

void add_one(MutableInt arg)
{
    arg.setValue(arg.getValue() + 1);
}
于 2012-07-11T16:49:16.067 回答
2

你不可以做这个。Java 只是按值传递。原语是显而易见的,但传递给对象的东西是引用,而不是对象本身。

于 2012-07-11T16:42:15.683 回答
0

正如您从其他答案中看到的那样,Java 纯粹是按值传递。对象通过一些所谓的“值引用”传递。由于Java中的对象只是一个指针引用,因此您可以将“值”视为对象在堆上的地址。因此,当您进行方法调用时,您将“值”(也称为地址)复制到方法参数:

Object x = new Object();
foo(x);

在对象创建期间

堆 --> 分配对象 (5000)

变量声明

堆栈 --> 分配局部变量 (1000)

变量赋值

堆栈地址 1000 设置为 5000(指向对象实例)

所以你可以看到这里有两个独立的内存分配。变量的“值”被认为是它在堆上的地址。

方法调用

堆栈 --> 分配方法参数 8000

堆栈地址 8000 设置为与传递的参数 5000 相同的值

这就是为什么如果您在方法中重新分配对象实例,它不会传播回调用者。您将更改堆栈位置 8000 处的堆位置。调用方法的堆栈位置 1000 仍然具有值 5000(原始对象实例)。

在 C 中这样想:

void method(myobject * obj);

您当然可以更改“obj”的字段,并且可以在本地执行此操作:

obj = new myobject();

但是调用者仍然会看到它传递的原始值。

Java 没有与 & 引用运算符类似的东西。

并且有内置的类可以用于您的目的。AtomicInteger、AtomicLong 等......是可变的,但您可能会因涉及同步而遭受性能损失。

我会推荐一个通用的 ValueHolder 类来解决您想要模拟通过引用传递的所有情况:

public class ValueHolder<T> {
    private T value;
    // getter/setter/constructor
}
于 2012-07-11T17:37:53.680 回答
-3
public int getOneMore(int val) {
  return val + 1;
}
于 2012-07-11T16:44:43.523 回答
-3

Java 允许对象的引用复制和原始类型(int、float 等)的 vlaue 复制。默认情况下是这样,并且不会更改。如果您需要在函数中更改 int 的值,则可以使用 Integer 类

于 2012-07-11T16:51:00.067 回答