java内存分析.
下面开始面向对象的内存分析:
堆和栈的区别
堆存放的是不确定的大小值(只有在运行的时候才知道)。
栈的存取速度快 堆的存取数速度慢一些存储空间大。
除了基本类型剩余的都是引用类型。
基本类型
在栈中开辟一块新的空间,将值放在开辟好的栈当中。
先声明,再赋值,然后再使用。
声明:在内存中开辟一块新的空间。
初始化:给该空间一个初始的值。例如:int初始化值为0。
赋值:将值放在开辟好的内存当中。
引用类型
在栈里面保存的是一个对象的引用地址。真正的对象是保存在堆里面。
Person person = new Person();
Person类型的变量person在栈中保存的是对象在堆里面的地址(不是堆内存的物理地址,只是可以通过这个地址找到对象),
真正的对象是通过new关键字创建的,保存在堆中。
(在堆和栈中各站一块内存)
String 是一种特殊的引用类型!!
例如:
String a = “Test”;
String b = a;
(a、b存在字符常量区)
首先,JAVA中字符串常量有个字符串池(string pool),每个字符串在创建的时候会在池中查找是否有这个字符串,
如果有则直接使用池中的对象,如果没有则在池中创建新的对象。
你的问题中:a是指向字符串池中内容为“Test”的对象的地址;
而b则是指向a的地址;
所以改变b肯定是不会改变a的内容的。
但是,如果如下:
String str1 = new String(“abc”);
String str2 = new String(“abc”);
这是str1和str2就是两个指两个保存String类型的引用。
例如:
StringBuffer 和 String 的区别
String 是个不可变的类(由final修饰),
String a = “ab”;
String b = “cd”;
String a = a + b;
内存中的执行过程:
用一个String 类型的变量,开辟一个空间存入”ab”,
用一个String 类型的变量,开辟一个空间存入”cd”,
再开辟一个新的空间,将以上两个”ab”和”cd”空间的值存入其中,将原来的变量 String a 指向 这个新的空间。
原来的 String a 的空间将会被垃圾回收机制回收。
如果以上String类型的是StringBuffer类型:
那么直接可以在原的内存空间后扩充追加一个空间,将新加入的值保存进去。
静态
被静态(static)修饰的,放在内存中的 data segment 块中。
静态变量不属于对象中,他是 class 共用的一块区间,他是单独存放在 data segment 中的。
常量
常量(final)也放在内存中的 data segment 块中。
System.out.println(“test”);这里的”test”也是常量
类
类是一个静态概念,类保存在代码区。
同一个类的每个对象共享该类的方法。
方法
方法是一个静态概念,保存在代码区。
只有在执行的时候才会占用内存。
同一个方法可以由很多对象同时在调用并且运行。
(方法中的参数是一个局部的变量,他在方法使用时创建,使用过以后销毁。)
方法的返回值暂时在 栈 里储存,此时该值没有名称。
对象
对象是new出来的,位于堆中。
new在创建过程中,就是将不同的值赋给对象的属性中,然后创建一个对象。
类的每个成员变量在不同的对象中都有不同的值(除了静态变量)而方法只有一份,执行的时候才会占用内存。
垃圾回收
你一直无法使用的对象,将被垃圾回收机制回收。
垃圾回收机制是隔一段时间回收一次的,他并不是及时回收的。
垃圾回收是如何完成的:
如果堆里面没有指向他的栈,那么该对象无法被调用。
所以此时回收机制会将其回收。
程序走完
当程序走完,main方法在内存中消失,栈里面的空间被清空,堆里面没有指向他的栈,垃圾回收机制就将其回收。