惯例先看一段代码
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 } }数组大小变了吗?看上去好像是变了,但其实根本没变。
对于数组ns来说,执行ns = new int[] { 68, 79, 91, 85, 62 };时,它指向一个5个元素的数组:
ns │ ▼ ┌───┬───┬───┬───┬───┬───┬───┐ │ │68 │79 │91 │85 │62 │ │ └───┴───┴───┴───┴───┴───┴───┘执行ns = new int[] { 1, 2, 3 };时,它指向一个新的3个元素的数组:
ns ──────────────────────┐ │ ▼ ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐ │ │68 │79 │91 │85 │62 │ │ 1 │ 2 │ 3 │ │ └───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘但是,原有的5个元素的数组并没有改变,只是无法通过变量ns引用到它们而已。
字符串数组如果数组元素不是基本类型,而是一个引用类型,那么,修改数组元素会有哪些不同?
字符串是引用类型,因此我们先定义一个字符串数组:
String[] names = { "ABC", "XYZ", "zoo" };对于String[]类型的数组变量names,它实际上包含3个元素,但每个元素都指向某个字符串对象:
┌─────────────────────────┐ 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,性质一样了。