Java中把内存分为两种:一种叫栈内存,一种叫堆内存。
栈内存:某一个函数被调用时,这个函数会在栈内存里面申请一片空间,以后在这个函数内部定义的变量,都会分配到这个函数所申请到的栈。当函数运行结束时,分配给函数的栈空间被收回,在这个函数中被定义的变量也随之被释放和消失。
堆内存:通过new产生的数组和对象分配在堆内存中。堆内存中分配的内存,由JVM提供的GC(垃圾回收机制)来管理。在堆内存中产生了一个数组对象后,我们还可以在栈中定义一个变量,这个栈中变量的取值等于堆中对象的首地址。栈内存中的变量就成了堆内存中数组或者对象的引用变量。我们以后就可以在程序中直接使用栈中的这个变量来访问我们在堆中分配的数组或者对象,引用变量相当于数组或者对象起的一个别名,或者代号。
引用变量是一个普通的变量,定义时在栈中分配;引用变量在被运行到它的作用域之外时就被释放,而我们的数组和对象本身是在堆中分配的,即使程序运行到使用new产生对象的语句所在的函数或者代码之后,我们刚才被产生的数组和对象也不会被释放。数组和对象只是在没有引用变量指向它,也就是没有任何引用变量的值等于它的首地址,它才会变成垃圾不会被使用,但是它任然占据着内存空间不放(这也就是我们Java比较吃内存的一个原因),在随后一个不确定的时间被垃圾回收器收走。
实际上,栈中的变量指向堆内存中的变量,这就是Java中的指针。
class ArrayTest
{
public static void main(String[] args)
{
int arr[]=new int[100];
int sum=0;
for(int i=0;i<100;i++)
{
sum+=arr;
}
}
}
我们可以int x [] = new int [100];分成两部分来写:int x [] ;和x=new int [100];。
第一部分相当于定义了一个普通的变量,只是这个变量中存放的数据是堆中某个对象的首地址。接着我们使用,这一句是在堆内存中产生了一个有100个元素整数类型的数组。
当一个对象被创建时,会对其中各种类型的成员变量自动进行初始化赋值。除了基本数据类型之外的变量都是应用类型。
成员变量 | 初始值 | byte | 0 | short | 0 | int | 0 | long | 0 | float
double | 0.0F
0.0D | char
bolean | '\u0000'
False |
Person p1 = new Person ();
执行完后的内存状态执行完后的内存状态执行完后的内存状态执行完后的内存状态
创建新的对象之后,我们就可以使用“对象名.对象成员”的格式,来访问对象的成员(包括属性和方法)。
public class Student
{
int age;
void shout()
{
System.out.println(age);
}
public static void main(String[] args)
{
Student p1=new Student();
Student p2=new Student();
pi.age=30;
p1.shout();
p2.shout();
}
}
|
|