我知道这个问题已经解决了很多次——但是我的 Java/C++ 知识太薄弱了,我几乎无法理解答案:-( ...我真正想要的只是一个超级简单的例子。
在 C++ 中,我可以编写以下内容:
void func()
{
int x = 3;
add_one(x);
// now x is 4.
}
void add_one(int &var)
{
var++;
}
我现在想看到的是用java达到同样效果的最简单的方法。
我知道这个问题已经解决了很多次——但是我的 Java/C++ 知识太薄弱了,我几乎无法理解答案:-( ...我真正想要的只是一个超级简单的例子。
在 C++ 中,我可以编写以下内容:
void func()
{
int x = 3;
add_one(x);
// now x is 4.
}
void add_one(int &var)
{
var++;
}
我现在想看到的是用java达到同样效果的最简单的方法。
你不能直接。最接近的方法是将值放入对象中,然后将引用(按值,因此引用被复制)传递给方法。
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]++;
}
这里我使用了一个数组,但是包装器可以是任何对象。
在 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);
}
你不可以做这个。Java 只是按值传递。原语是显而易见的,但传递给对象的东西是引用,而不是对象本身。
正如您从其他答案中看到的那样,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
}
public int getOneMore(int val) {
return val + 1;
}
Java 允许对象的引用复制和原始类型(int、float 等)的 vlaue 复制。默认情况下是这样,并且不会更改。如果您需要在函数中更改 int 的值,则可以使用 Integer 类