我试图理解下面写的两个Java程序之间的区别:
public class Swapping {
public static void main(String[] args) {
IntWrap i = new IntWrap(10);
IntWrap j = new IntWrap(20);
swap(i, j);
System.out.println("i " + i.i + ", j " + j.i);
}
public static void swap(IntWrap i , IntWrap j){
int x = i.i;
i.i = j.i;
j.i = x;
System.out.println("i " + i.i + ", j " + j.i);
}
}
public class IntWrap {
int i;
public IntWrap(int i){
this.i = i;
}
}
输出:
i 20, j 10
i 20, j 10
第二个:
public class Swapping {
public static void main(String[] args) {
Integer i = new Integer(10);
Integer j = new Integer(20);
swap(i, j);
System.out.println("i " + i + ", j " + j);
}
public static void swap(Integer i , Integer j){
Integer temp = new Integer(i);
i = j;
j = temp;
System.out.println("i " + i + ", j " + j);
}
}
输出:
i 20, j 10
i 10, j 20
我无法理解即使我传递了Integer对象,它也应该在原始程序中交换。如果我在它上面写了包装类,那么它创建了什么区别,因为我只是再次传递对象。
答案 0 :(得分:4)
所有方法参数(包括对象引用)都是通过Java中的值传递的。您可以为方法参数指定任何值 - 不会修改调用代码中的原始值。但是,您可以修改传递的对象本身,并且在方法返回时更改将保持不变。
J2SE API中有旧的Holder类,专门用于支持对具有“可返回参数”(例如IntHolder或StringHolder)的方法的调用。它们主要与IDL语言生成的代码一起使用,因为IDL需要支持in,out和inout参数。这些持有人在其他代码中非常罕见。
您还可以使用数组模拟通过引用传递:
String [] a = new String[1]; String [] b = new String[1];
void swap(String [] a, String [] b) {
String t = a[0]; a[0] = b[0]; b[0] = t;
}
答案 1 :(得分:1)
的UPS。 Integer
对象在Java中是不可变的。您不能从其他方法更改其内部值,也不能。只创建新的Integer
对象。
答案 2 :(得分:1)
Java使用call-by-value传递所有参数。当您将对象传递给函数时,对象引用(对象的地址)将通过value传递。在第二个程序交换中,您将分配i = j和J =温度。 所以我= 20的地址 j =地址10(新对象) 但是从交换返回之后,在主程序中我仍然指向10并且j指向20.这就是为什么你在主程序中得到10和20的原因。
但是在第一个程序中,您将对象的地址传递给swap函数,而在swap函数中,您正在修改这些地址所指向的对象的内容。这就是为什么它会在main方法中反映出来。
答案 3 :(得分:0)
(如果你不知道指针和参考文献,我建议你稍微讨论它们,那么这个世界会更有意义 - Intro to Pointers)
归结为最简单的解释,java有两种方式来回传递所有内容:
Pass-by = Value:用于不可变对象( String,Integer,Double等)。如果重新创建对象,这些值不会更改,但有一个例外。
String x = "World"; <- String x = new String("World");
x = "Hello"; <- x = new String("Hello");
x = x + " World"; <- x = new String("Hello" + " World");
printOutString(x); <- printOutString("Hello World");
在一个记忆位置举行。任何更改都会创建一个与前一个无关的新对象,并查看单独的内存位置。
Pass-by-reference:用于非不可变对象( Classes,int,double等)。这些值可以更改,并且仍然保留在内存中的旧位置。
int i = 1;
i = 2; <- value at <reference-to-memory-as-value> = 2;
i = i + 1; <- value at <reference-to-memory-as-value> + 1;
printOutInteger(i); <- printOutInteger(value at <reference-to-memory-as-value>);
对此对象的任何更改都是对内存位置进行的。因此,位置永远不会更改(除非您创建新对象)。
您的计划也是如此。在方法中说出一件事的对象然后恢复为先前的值。在某种程度上,你是Operator Overloading
。您为要发送的异议(在这种情况下为Integer
)分配了新值,但您已在方法中传递了值Integer i
的值,因为{{1是不可变的,正在查看main方法中Integer
的不同内存位置。因此,当方法退出时,您传递的对象将被丢弃,Integer i
和Integer i
现在会查看其原始内存位置。
当您使用j
个对象传递类时,因为它们 NOT 不可变,所以传递了内存位置(按值)并且处理了这些位置的值。这就是为什么这里的变化显示在原始对象中。
我希望这会有所帮助