Java 从数组来看值传递和引用传递

从数组来看值传递和引用传递

惯例先看一段代码java

public class DemoCollection14 {
    public static void main(String[] args) {

        String [] strs = {"zs", "ls", "wu"};

        for (String str : strs) {
            strs[0] = null;
            System.out.println(str);
        }

        
        for (String str : strs) {

            System.out.println(str);
        }
    }
}

//输出:
//		zs
//		ls
//		wu
//
//		null
//		ls
//		wu
要想搞懂这道题,先看下面讲解

从新学习数组(此处引用了廖雪峰老师的讲解)数组

基本类型数组

数组是引用类型,而且数组大小不可变学习

public class Main {
    public static void main(String[] args) {
        // 5位同窗的成绩:
        int[] ns;
        ns = new int[] { 68, 79, 91, 85, 62 };
        System.out.println(ns.length); // 5
        ns = new int[] { 1, 2, 3 };
        System.out.println(ns.length); // 3
    }
}

数组大小变了吗?看上去好像是变了,但其实根本没变。spa

对于数组ns来讲,执行ns = new int[] { 68, 79, 91, 85, 62 };时,它指向一个5个元素的数组:code

ns
      │
      ▼
┌───┬───┬───┬───┬───┬───┬───┐
│   │68 │79 │91 │85 │62 │   │
└───┴───┴───┴───┴───┴───┴───┘

执行ns = new int[] { 1, 2, 3 };时,它指向一个新的3个元素的数组:对象

ns ──────────────────────┐
                              │
                              ▼
┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐
│   │68 │79 │91 │85 │62 │   │ 1 │ 2 │ 3 │   │
└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘

可是,原有的5个元素的数组并无改变,只是没法经过变量ns引用到它们而已。ci

字符串数组

若是数组元素不是基本类型,而是一个引用类型,那么,修改数组元素会有哪些不一样?字符串

字符串是引用类型,所以咱们先定义一个字符串数组:get

String[] names = {
    "ABC", "XYZ", "zoo"
};

对于String[]类型的数组变量names,它实际上包含3个元素,但每一个元素都指向某个字符串对象:io

┌─────────────────────────┐
    names │   ┌─────────────────────┼───────────┐
      │   │   │                     │           │
      ▼   │   │                     ▼           ▼
┌───┬───┬─┴─┬─┴─┬───┬───────┬───┬───────┬───┬───────┬───┐
│   │░░░│░░░│░░░│   │ "ABC" │   │ "XYZ" │   │ "zoo" │   │
└───┴─┬─┴───┴───┴───┴───────┴───┴───────┴───┴───────┴───┘
      │                 ▲
      └─────────────────┘

names[1]进行赋值,例如names[1] = "cat";,效果以下:

┌─────────────────────────────────────────────────┐
    names │   ┌─────────────────────────────────┐           │
      │   │   │                                 │           │
      ▼   │   │                                 ▼           ▼
┌───┬───┬─┴─┬─┴─┬───┬───────┬───┬───────┬───┬───────┬───┬───────┬───┐
│   │░░░│░░░│░░░│   │ "ABC" │   │ "XYZ" │   │ "zoo" │   │ "cat" │   │
└───┴─┬─┴───┴───┴───┴───────┴───┴───────┴───┴───────┴───┴───────┴───┘
      │                 ▲
      └─────────────────┘

这里注意到原来names[1]指向的字符串"XYZ"并无改变,仅仅是将names[1]的引用从指向"XYZ"改为了指向"cat",其结果是字符串"XYZ"再也没法经过names[1]访问到了。

对“指向”有了更深刻的理解后,试解释以下代码:

public class Main {
    public static void main(String[] args) {
        String[] names = {"ABC", "XYZ", "zoo"};
        String s = names[1];
        names[1] = "cat";
        System.out.println(s); // s是"XYZ"仍是"cat"?
    }
}

//输出"XYZ"

//解释缘由:
//names字符串数组建立好后,s指向names[1]这个位置。
//可是呢,name[1]可不是把原数据XYZ更改成了cat,而是从新指向了存有cat的那个空间地址。
//故s仍是指向原来那个位置,故输出的是XYZ

再回到开始的那个问题:

public class DemoCollection14 {
    public static void main(String[] args) {

        String [] strs = {"zs", "ls", "wu"};

        for (String str : strs) {
            strs[0] = null;
            System.out.println(str);
        }

        
        for (String str : strs) {

            System.out.println(str);
        }
    }
}

//输出:
//		zs
//		ls
//		wu
//
//		null
//		ls
//		wu

foreach,其实就是迭代器。迭代器,不是传统意义的for循环输出数组数据。
    而是定义了String str,依次str=strs[i],并输出str。故和前面的xyz,性质同样了。