Java 传值和传引用的区别?

前提引言:要理清这个问题需要明确几个问题?什么是值?什么是引用?如何区分是传的值还是引用?

先看区别:
传值:传递的是值的副本。方法中对副本的修改,不会影响到本身。
传引用:本质传递的就是地址,此时,形参和实参指向同一个内存地址。对副本的操作会影响本身,单如设置为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; //一旦赋值,就不能改变。
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值