我无法理解为什么重载函数'increase'不会改变Integer但会改变Point。 'Integer'类的支持是包装int,因此它将是一个引用Type。
import java.awt.Point;
public class test2 {
public static void main(String[] args) {
///1
Integer i = new Integer(0);
increase(i);
System.out.println(i);
///2
Point p = new Point(0,0);
increase(p);
System.out.println(p);
}
public static void increase(Integer i){
i = 1;
}
public static void increase(Point p){
p.setLocation(1, 1);
}
}
输出为:
0
java.awt.Point[x=1,y=1]
另外,它们是一种通过Java引用将变量传递给函数的简单方法吗?
答案 0 :(得分:6)
Integer类是一个不可变类,这意味着它的内容在创建后无法更改。
此外,Java是按值传递的,因此变量i
按值传递,并且它在函数内部更改的事实对调用者没有影响。
请阅读此处:http://en.wikipedia.org/wiki/Immutable_object以获取有关不可变对象的更多信息。
答案 1 :(得分:3)
简单的答案是Java使用pass by value,而不是通过引用传递。
在Point
的情况下,该方法正在更改引用传递给方法的点对象的字段。
在Integer
的情况下,该方法只是为局部变量i
分配一个新值。这不会更新调用方法中的变量i
,因为Java使用pass by reference。
另一个问题是Integer
没有setValue
方法,因为它是不可变的。如果您想要执行与方法的Point
版本相同的操作,则必须定义具有getter和setter的IntegerHolder
类以及{{{}}等方法。 1}},您的应用程序需要。 (或者,在第三方库中找到这样的课程。)
答案 2 :(得分:2)
Integer
个对象是不可变的,即您无法更改它们。如果可以的话,语法就像
i.setValue(1);
如果要通过引用传递非对象,可以将其包装在长度为1的数组中,或者(更好)创建一个简单的包装器。但是,没有理由这样做 - 不要从C 1:1移植代码。通常,您应该有一个语义加载的对象,例如Account
,您可以在其上调用increase
和decrease
(或者只是setBalance
)方法。
答案 3 :(得分:1)
在此功能中:
public static void increase(Integer i){
i = 1;
}
autoboxing使其等同于:
public static void increase(Integer i){
i = new Integer(1);
}
即。它会更改i
包含的引用,而不是它包含的值。 Integer
对象本身是不可变的,实际上没有办法在创建它之后改变它的值。
由于该引用是局部变量,因此对它的任何更改都不会影响传入的变量。
答案 4 :(得分:0)
当您撰写i = 1
时,您要将i
参数更改为指向新的已装箱Integer
实例。
您传递给函数的原始Integer
实例不是 - 并且无法更改 - Integer
是不可变的
答案 5 :(得分:0)
在这里回答:http://www.javaworld.com/javaworld/javaqa/2000-06/01-qa-0602-immutable.html 此参考可能很有用:http://javadude.com/articles/passbyvalue.htm
答案 6 :(得分:0)
如果您希望这两种方法相同,那么第二种方法将如下所示:
public static void increase(Point p){
p = new Point(1, 1);
}
然后你会看到它在这里输出原始点。
在Java中没有通过引用将变量传递给函数。
您可以通过传递包含变量的对象来模拟它(就像您在increase(Point)
方法中所做的那样) - 您必须确保分配给变量,而不是分配给包含变量的对象变量
如前所述,有几个“可变包装器”(例如标准API中的org.omg.CORBA.IntHolder
和java.util.concurrent.AtomicInteger
),但创建自己的包装并不困难,在大多数情况下它最好使用合理的“业务对象”,比如“账户”。