作者:禅楼望月(http://www.cnblogs.com/yaoyinglong/)
静态的Java数组
Java语言是典型的静态语言,因而,数组也是静态的,即当该数组被初始化之后,该数组的长度是不可变的。
java 语言的数组变量是引用类型,什么意思呢?意思就是,数组变量并不是数组本身,它只是指向堆内存中的数组对象。如:
这3个变量以及各自引用的数组在内存中的分配如图:
我们平时可以通过改变数组变量的指向,让它指向的堆内存中的其他数组对象(前提是他们的编译类型是兼容的),从表面上看起来好像是更改了数组的长度。但是其实我们只是让该数组变量指向了另一个数组对象,而原来的那个数组对象再没有其他数组变量指向的情况下等待垃圾回收。
对数组变量来说,它并不需要进行所谓的初始化,只是让数组变量指向一个有效的数组对象即可。
对Java程序来说,所有的引用类型的变量都不需要经过所谓的初始化,需要进行初始化的只是该引用变量所引用的对象。
所有的局部变量都是存放在栈内存中,不管其是引用类型的变量还是基本类型的变量,都是存储在各自的方法栈区中;但引用类型变量所引用的对象(包括数组、普通的Java对象)则总是存储在堆内存中。
对于Java,堆内存中的对象(不管是数组还是普通Java对象)通常不允许直接访问,为了访问堆内存中的对象,通常只能通过引用变量。
数组变量都是存储在栈内存中的,但数组元素则作为数组对象的一部分被保存在堆内存中,无论它们是基本类型的数组元素还是引用类型的数组元素。
基本类型数组的初始化
对于基本类型数组而言,数组元素的值直接存储在对应的数组元素中,因此程序直接为数组分配内存空间,再将数组元素的值存入对应的内存里即可。
intArr只是一个数组变量,它存在它所在的方法栈区中,它实际指向对内存中的一个数组对象。所以应该将数组变量与数组对象分开。
引用类型数组的初始化
比基本类型数组初始化复杂了一点:引用类型数组元素里面存还是引用,而不是引用对象本身,它指向堆内存中另一块内存单元(这块内存中存储了引用变量所指向的对象:数组或者Java对象)。
public class Person { private String name; private int age; public Person(String name,int age) { this.name=name; this.age=age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String toString(){ return "我叫"+name+" 我的年龄是:"+age; } public static void main(String[] args) { Person[] students=new Person[3]; Person xiaoming=new Person("小明", 10); Person xiaohong=new Person("小红", 15); Person xiaozhang=new Person("小张", 20); students[0]=xiaoming; students[1]=xiaohong; students[2]=xiaozhang; System.out.println(Arrays.toString(students)); System.out.println("xiaoming和students[0]是不是指向同一个Java对象?-->"+(xiaoming==students[0])); xiaohong.setName("我的名字改了"); System.out.println("通过变量xiaoming修改了它指向的Java对象的name属性:"+xiaohong.getName()); System.out.print("获取students[1]的name属性为:"); System.out.println(students[1].getName()); } }
打印出的结果为:
main函数执行过程的内存示意: