我对Java中的逐值机制感到困惑,尽管我读过一些关于它的问题,比如this和this。
我认为原语类型是通过函数参数中的值传递的,所以即使它在函数作用域中被更改,它也不会更改它的值。
public class A {
void function(int i) {
i = 3;
}
public static void main(String[] args) {
int i = 2;
function(i);
System.out.println(i); // variable `i` won't change
}
}但是类对象是通过函数参数中引用的值传递的,因此如果函数范围中的引用被更改,它将更改其值。
public class Obj{
public double calPrice;
public boolean isTop;
public boolean isCate;
public List<Integer> cList;
public RPCRecord(double c, boolean iT, boolean iC, List<Integer> cL) {
calPrice = c;
isTop = iT;
isCate = iC;
cList = cL;
}
}
void f2(Obj o) {
List<Integer> l1 = new ArrayList<Integer>(){{
add(1);
add(2);
add(3);
}};
Obj o2 = new Obj(10.0, true, false, l1);
o = o2;
}
void f3(Obj obj) {
obj.calPrice = 123123.1;
obj.isTop = false;
obj.add(10);
}
public class A {
public static void main(String[] args) {
Obj ojb = new Obj();
f2(ojb);
System.out.println(ojb); // Object `obj` will change
f3(ojb);
System.out.println(ojb); // Object `obj` will change
}
}请原谅我对Java参数机制不够熟悉。
我是这么想的对吗?
发布于 2022-01-17 05:06:18
我认为这对于Java中的逐值传递来说是一种常见的混淆。
如果您想从规则的角度来考虑它:如果将对象(引用)传递给方法,则不能更改传入的对象。换句话说,您不能更改对另一个对象的引用。
您能够做的是更改对象中的内容--上面的f3方法应该可以更改传递给它的对象中的内容。
但是,您不能--就像您在f2中试图做的那样--将传入的对象(A类中的ojb)更改为另一个对象。若要从方法返回对象,必须在方法的return语句中返回该对象,或者必须是另一个对象中的字段,以便在另一个对象中更改该对象。
现在,如果您想要更低层次的解释,而不是规则:
当您将对象变量名称作为参数放入Java中的方法时,您将传递一个指向该对象的“指针”。您可以将它看作是由内存中的地址表示的对象,并且传递一个保存该地址的变量。您可以将保存对象地址的变量看作是通过值传递的,即使是通过引用传递对象。
该方法将参数作为一种特殊的变量来获取,并可以使用参数变量引用该对象。该方法可以更改变量;它不能为调用方更改它。
从上面采取你的方法:
void f2(Obj o) {
List<Integer> l1 = new ArrayList<Integer>(){{
add(1);
add(2);
add(3);
}};
Obj o2 = new Obj(10.0, true, false, l1);
o = o2;
}调用者传入包含指向对象的指针的参数“变量”;f2方法调用该参数变量o。f2可以更改参数变量的值。但是,该地址上的任何对象仍然驻留在该地址上,而持有该地址的调用者中的任何变量仍然持有该地址。
查看它的另一种方法是:假设调用方将一个名为george的变量传递给您的f2方法:
SomeObject george = new SomeObject();
f2(george);假设george的地址是1234。然后,我们可以将o在f2中想象为持有1234,即george的地址。f2用Obj o2 = new Obj(10.0, true, false, l1);创建一个新对象,假设o2位于地址5678。o = o2语句在您的f2中所做的是将5678赋值给o,替换以前存在的1234。这不会影响调用者;george仍然在1234。f2更改了一个保存george地址的变量,但调用方无法知道这一点。
发布于 2022-01-17 04:58:49
在调用具有基元类型的方法时,传递(字节、短、字符、int、长、浮点、双、布尔值)值,其中包含对象-引用。
换句话说,不可能在调用方法时将原始变量(如int )作为参数传递来更改它的初始值。但是它对一个对象是可行的,但只有在它是一个可变对象的情况下才是可行的。例如,您可以使用自定义类Obj的实例或实例,但不能更改BigInteger或String,这些类设计为不可变。
https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html
https://stackoverflow.com/questions/70736350
复制相似问题