美文网首页
JAVA 的值传递

JAVA 的值传递

作者: 又是很难取名字的付小白 | 来源:发表于2017-07-27 21:28 被阅读0次

    JAVA 的值传递

    预备知识

    1. 对象变量与对象
      在 Java 中,任何对象变量的值都是对存储在另外一个地方(堆)的一个对象的引用。
      对象变量本质仍然是变量,存储在栈中,而对象则是类的实例,存储在堆中。如:

          List<Date> dateList = new ArrayList<>();
      

      对象变量 dateList 的值是对存在于堆中的一个 ArrayList 对象的引用。如下图:


      image.png
    2. 基本类型
      4 种整形:byte, short, int, long
      2 种浮点型:float, double
      1 种字符类型:char
      1 种表示真值的类型:boolean

    3. 值传递(call by value)
      方法接收的是调用者提供的值,方法不能修改对应的变量值。

    4. 引用传递(call by reference)
      方法接收的是调用者提供的变量地址,方法可以修改对应的变量值。


    JAVA 中的方法参数

    Java 中仅存在值传递(call by value),并不存在引用传递(call by reference)。即 Java 方法得到的是所有参数值的一个拷贝,并不是参数值本身(地址),方法并不能修改任何参数值的内容。

    例一
        public static void main(String[] args) {
            int a = 34;
            System.out.println(a);
            changeInt(a);
            System.out.println(a);
        }
        
        public static void changeInt(int a2) {
            a2 = 78;
        }
    
    
    1. 上述结果是:
      34
      34

    2. 原因:
      当调用 changeInt(a) 时,只是将 a 的值传递给 changeInt 方法,其本身地址没有传递。
      changeInt 方法中的变量 a2 和 main 方法中的变量 a 存储在栈的两个位置,changeInt 方法中的 a2 的值改变并不影响 main 方法中的 a。

    3. 执行步骤:

      1. a2 初始化为 a 的值的拷贝(34);
      2. a2 被重新赋值为 78,但此时 a 的值依然是 34;
      3. changeInt 方法结束后,a2 的作用域结束,不再被使用
    image.png
    例二
        public static void main(String[] args) {
            List<String> list = new ArrayList<>();
            System.out.println(list);
            changeList1(list);
            System.out.println(list);
            changeList2(list);
            System.out.println(list);
        }
        
        public static void changeList1(List<String> list1) {
            list1.add("1");
        }
        
        public static void changeList2(List<String> list2) {
            list2 = new LinkedList<>();
        }
    
    1. 输出结果:
      []
      [1]
      [1]

    2. 原因:
      例二和例一比较类似,区别在于:此时,方法参数不是基本数据类型,而是一个对象引用,也就是传递了变量 list 的值 —— new ArrayList 这个对象的地址,简称对象A。
      changeList1 和 changeList2 方法得到的都是对象A的地址,即变量 list1 和变量 list2 都被赋初值:对象A的地址(如图)。
      此时请注意,变量 list1 和变量 list2 仍然不同于变量 list。它们三个存在在栈上的不同位置。
      当变量 list1 增加元素时,是给对象A增加元素。
      而变量 list2 被指向了一个新的对象B。在方法结束时被丢弃了,并没有改变变量 list 的值。

    3. 执行步骤

      1. 变量 list 初始化为 对象 A
      2. 打印变量 list,也就是打印对象 A,即 []
      3. 变量 list1 被初始化为变量 list 的值的拷贝,也就是对象 A 的地址;
      4. 变量 list1 增加元素 "1",也就是对象 A 增加元素 "1";
      5. 打印变量list,也就是打印对象 A 的值,即 [1];
      6. 变量 list2 被初始化为变量 list 的值的拷贝,也就是对象 A 的地址;
      7. 变量 list2 被赋值一个 LinkedList 对象,称之为对象 B;
      8. 变量 list2 的作用域结束,对象 B 同时结束,被丢弃;
      9. 打印变量list,也就是打印对象 A 的值,即 [1];
    image.png image.png

    总结

    1. Java 中仅有值传递,不存在引用传递。当传递一个对象时,实际上传递的是对象参数(对象变量)的值,也就是该对象的引用的地址;
    2. 一个方法不能修改一个基本数据类型的参数;
    3. 一个方法可以改变一个对象参数的状态
    4. 一个方法不能实现让对象参数引用一个新的对象;

    相关文章

      网友评论

          本文标题:JAVA 的值传递

          本文链接:https://www.haomeiwen.com/subject/criokxtx.html