什么是值传递和引用传递?(总结及代码文字解释????)

总结:
值传递是对基本型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量.
引用传递一般是对于对象型变量而言的,传递的是该对象地址的一个副本, 并不是原对象本身 。
一般认为,java内的传递都是值传递. java中实例对象的传递是引用传递 。

(关注Java刘老师,共同学习)

  • -------解释如下:
    值传递:指的是在方法调用时,传递的是参数是按值的拷贝传递。
    特点:传递的是值的拷贝,也就是传递后就互不相关了。
    引用传递:指的是在方法调用时,传递的参数是按引用进行传递,其实传递的是引用的地址,也就是变量所对应的内存空间的地址。
    特点:传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。
    对于这两种传参方式,假如你写过一些java程序后,你就会发现这不就是看传的参数是基本类型的还是引用类型的吗?(其中比较特殊一点的是String类型和基本类型的包装类类型,它们也是按值传递的,但它是属于引用类型,对于还不知道包装类型的,关于自动拆箱与自动装箱,我们直接分析代码运行结果:public class Test {

    public void test1(int a) {
    // 值传递
    a = 1;
    System.out.println(“test1中的a=” + a);
    }

    public static void main(String[] args) {
    Test t = new Test();
    int a = 2;
    t.test1(a);// 值传递不影响mian方法里的a
    System.out.println(“main方法里的a=” + a);

    }
    }
    测试基本类型值传递对于基本类型,这里我只举了int类型的值传递例子,可以看到在main方法里的a与test1方法里面的a并没有什么关系,在test1方法里面改变a的值并不能影响main方法里的a值。值传递,二者并不影响那对于引用类型String和基本类型的包装类而言,它们也都是值传递。所以我们先来了解一波String类型。public class Test {

    public void test1(String a) {
    // 值传递
    //1、a = “test1”;
    a=new String(“test1”);
    System.out.println(“test1中的a=” + a);
    }

    public static void main(String[] args) {
    Test t = new Test();
    //1、String a = “main”;
    String a=new String(“main”);
    t.test1(a);// 值传递不影响mian方法里的a
    System.out.println(“main方法里的a=” + a);

    }
    }
    String类型采用值传递分析上面代码,可以看出与int类型值传递的效果是一样的。对于String类型,我们有两种常用的创建对象的方法,一种是用字符串直接量,一种是用字符数组。但java把字符串直接量也当做是String对象,因此,利用字符串直接量可以按如下两种方式去创建。//利用字符串直接值创建对象的方法
    String s1= new String(“hello”);
    String s2=“hello”;但这两种方式却不能说完全一样,且看测试代码如下:根据==判断为false可知二者并不是指向同一个引用,但我们之前说String类型对象是不可变得,它的内容是不能改变的,既然根据equals判断为true,它们的内容是一样的,那为什么二者却不是指向同一个引用呢?其实,很简单,正是由于字符串在程序设计中被频繁使用,当它本身又不可变,所以JVM为了提高效率并节约内存,对具有相同字节序列的字符串直接量使用同一个实例。这个实例叫做“限定(interned)的字符串”。因此两种创建对象的方式其实是不同的,s2是指向了一个限定的字符串“hello”,这个是在栈内存中的,而s1则是实实在在指向了创建的一个字符串对象,它的值为“hello”,这个则是在堆内存的。两种创建方式的比较假如你对什么是限定字符串和字符串不可变性的概念理解了,下面的一段代码你就应该能很快理解了:public class Test {

    public static void main(String[] args) {
    Test t = new Test();
    String s1 = new String(“hello”);
    String s4 = new String(“hello”);
    // 限定字符串
    String s2 = “hello”;
    String s3 = “hello”;

     System.out.println("s1==s4: " + (s1 == s4));
     System.out.println("s1==s2: " + (s1 == s2));
     System.out.println("s2==s3: " + (s2 == s3));
             // 对字符串不可变性的测试
     s3 += "world";
     System.out.println("s3: " + s3);
    

    }
    }
    分析:首先对于s1和s4大家应该好理解,创建了两个对象,引用肯定是不相同的;其次对于限定字符串“hello”,由于s2与s3均指向它,因此二者的引用是相同的,所以s2==s3为true。至于s1和s2,上面已经解释过了。最后我再说明一下String类型的不变性。看到s3输出为helloworld,不明所以的你可能以为这个不就和不变性矛盾了吗?其实不然,且看下图:不变性图解(注:此图有问题,"hello"以及“helloworld”都应该在栈内存中)看完图,你就会明白,不变的是“hello”,但s3的引用关系发生了改变,指向了存放"helloworld"的内存空间。二、引用传递看完上面int和String类型的值传递,我们再来看下什么是引用传递。事实上,java里面参数传递只有值传递一种,因为引用传递可以相当于传递的是引用值。至于引用值是什么,我们可以类比C语言得指针变量,它存放的也是一段内存空间的地址。引用传递事实上更好理解,尤其是你对C语言中指针概念有所了解的话,这个直接分析一遍代码,就能理解了。
    public class Test {
    private void test1(A a) {
    a.age=1;
    System.out.println("test1中a.age: "+a.age);
    }
    public static void main(String[] args) {
    Test t = new Test();
    A a = new A();
    a.age=2;
    t.test1(a);
    System.out.println("main中a.age: "+a.age);

    }
    }

class A {
public int age = 0;
}
引用传递测试结果首先在main方法中,我们创建了A类的一个对象a,并把它的age设为2,然后我们将a作为参数传到test1方法中,并再次修改age值,然后输出test1中a.age值,执行完后返回到main函数里,再输出main中a.age,且二者结果一致。结合内存图示来理解,会很容易理解:引用传递在不同方法之间,看似传递的是一个对象,但其实对象的位置并没有动,只是将存放对象的内存地址进行了传递,这样当改变对象的一些属性时,也会的的确确改变堆内存中对象的某些属性值,因此返回到main函数后由于a依旧指向同一块区域,所以去读取数据的时候,值就会变化了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值