你能解释一下这段代码的行为:
class Test{
public List<String> change(List<String> s){
List<String> tmp = s;
tmp.add("test");
return tmp;
}
public Integer change(Integer s){
Integer tmp = s;
tmp++;
return tmp;
}
}
public class Main {
public static void main(String[] args) {
List<String> l = new ArrayList<String>();
Integer i = new Integer(10);
Test t = new Test();
System.out.println(l);
t.change(l);
System.out.println(l);
System.out.println(i);
t.change(i);
System.out.println(i);
}
}
结果是:
[]
[test]
10
10
为什么我的列表被更改,即使在change()方法内部我创建了tmp变量并归因于它传递了参数而我的Integer在相同的情况下没有变化?
答案 0 :(得分:3)
诀窍在于:
Integer tmp = s;
tmp++;
这大致相当于*:
Integer tmp = s;
int tmp_unboxed = tmp.intValue;
tmp_unboxed++;
tmp = new Integer( tmp_unboxed );
Integer
unboxed为int
,然后int
会递增,最后结果为boxed到另一个Integer
对象
如您所见,原始整数尚未修改,而是创建了一个新整数。而在列表示例中,您可以修改原始列表。
*我过度简化了这种情况,以便更轻松地解决问题:特别是你不总是得到一个全新的Integer
个实例,但你总是得到一个不同的 { {1}}实例比你开始时的实例..
答案 1 :(得分:1)
这是因为Integer(与String,Double等相同)是不可变的。这意味着你无法改变该对象的价值。
那么这里会发生什么?
if (isset($_GET['id']) && is_numeric($_GET['id']))
{
$id = $_GET['id'];
if ( $stmt3 = $mysqli->query ( "INSERT INTO tbluser (username, password,email,role = 1) SELECT companyUsername,companyPassword,companyEmail FROM tblpartner WHERE companyId=?" ));
}
在这一行Integer tmp = s;
tmp++;
,Integer的实例(我们可以称之为X)在内存中,对它的引用存储在变量Integer tmp = s;
中。您将此X引用复制到变量s
。
在这一行tmp
中,因为Integer是不可变的,所以新实例Y在内存中创建,它被赋予实例X的值,然后递增,然后对它的引用存储在变量{{1 }}
变量X仍在内存中且值不变。
答案 2 :(得分:1)
整数对象是不可变的。从
中捕获结果int returnedObject = t.change(i);
并打印returnedObject
,您将看到修改后的对象
另一方面,列表对象是可变的。这就是为什么变化反映在同一个对象本身
答案 3 :(得分:1)
这是由于java的两个特性:autoboxing和pass-by-reference。
传递引用意味着如果将Object用作方法的参数,则将其在内存中的位置传递给该方法。因此,作为参数传递的List
被修改。
Integer
也是通过引用传递的,但是这里的autoboxing适用。 Integer
本身是Object
,不支持运营商; Integer
是不可改变的!自动装箱将Integer
或基元类型的对象表示转换为基元类型。因此,Integer
转换为int
,int
被修改。但是,此操作不会影响Integer
- 对象。 Integer
中的change
基本上可以用这种方式大致描述:
public Integer change(Integer s){
//store reference to `s` in tmp
Integer tmp = s;
//unbox tmp and increment
tmp++;
//return tmp
return tmp;
}
Unboxing:
int unboxed = tmp.intValue();
unboxed++;
tmp = new Integer(unboxed);