前提引言:要理清这个问题需要明确几个问题?什么是值?什么是引用?如何区分是传的值还是引用?
先看区别:
传值:传递的是值的副本。方法中对副本的修改,不会影响到本身。
传引用:本质传递的就是地址,此时,形参和实参指向同一个内存地址。对副本的操作会影响本身,单如设置为null,重新指向其他对象等操作,则不会。
注意:string和包装类不会被改变
直接上代码演示:
//值传递
public class ValueTest {
public static void main(String[] args) {
int value = 1;
System.out.println("old = " + value);
add(value);
System.out.println("now = " + value);
}
private static void add(int i){
i = i* 5;
}
}
运行结果:
old = 1
now = 1
再看对象传递:
//对象传递
public class ObjectTest{
public static class A{
private int value;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
public static void main(String[] args) {
A a= new A();
a.setValue(1);
System.out.println("old= " + a.getValue());
change(a);
System.out.println("now = [" + a.getValue());
}
private static void change(A a){
a.setValue(2);
}
}
运行结果:
old = 1
now = 2
传String类型:
// String
public class StringTest{
public static void main(String[] args) {
String s = "begin";
System.out.println("old= " + s );
apend(s);
System.out.println("now= " + s );
}
private static void apend(String i){
i = i + " test value";
}
}
old = begin
now = begin
**这里可能会有疑问,为什么我传了一对象,没改变呢?**这里其实涉及string的底层实现。
string的底层有final修饰,本身值就是不能在被更改的,string拼接的过程其实在常量池中找对应字符串是否存在,不存在就创建然后把地址给到我们的string对象,so你明白了吧!
传包装类型:
public class test{
public void add(Integer i){
System.out.println("i原地址:"+System.identityHashCode(i));
i=3;
System.out.println("i赋值地址:"+System.identityHashCode(i));
}
@Test
public void test(){
Integer a=5;
System.out.println("a原地址:"+System.identityHashCode(a));
add(a);
System.out.println("a传参后地址:"+System.identityHashCode(a));
a=10;
System.out.println("a赋值地址:"+System.identityHashCode(a));
System.out.println(a);
}
运行结果:
a原地址:352359770
i原地址:352359770
i赋值地址:243745864
a传参后地址:352359770
a赋值地址:699780352
10
由于jdk1.5自动装箱的特性,实际情况是等价于执行 i = Integer.valueOf(3);valueOf()方法 参看源码 会根据传入的数值 如果在-128-127之间 就从常量池中获取一个Integer对象返回;如果不在范围内 会new Integer(3)返回。即是说Integer的地址会随着值的改变而改变!
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
还需要注意的一点是:在Integer源码中,int值是final修饰的,不可以改变
class Integer{
final int value; //一旦赋值,就不能改变。
}