【不会编程的麦兜】-Java基础:聊聊String存储管理
- 浅谈java内存
- 实例说明一切
浅谈java内存
学习过java我们都知道,在java中,JVM运行的时候,将内存分为两个部分,一部分是堆,一部分是栈。堆中存放的是创建对象,而栈中存放的则是方法调用过程中的局部变量或引用。在设计JAVA字符串对象内存实现的时候,在堆中又开辟了一块很小的内存,称之为字符串常量池,专门用来存放特定的字符串对象的。
例如:
String str1 = new String("Timo");//存放在堆中
String str2 = "Timo";//存放在字符串常量中
Java堆(Java Heap)是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内存区域。在此区域的唯一目的就是存放对象实例,几乎所有的对象实例都是在这里分配内存,但是这个对象的引用却是在栈(Stack)中分配。因此,执行String s = new String(“s”)时,需要从两个地方分配内存:在堆中为String对象分配内存,在栈中为引用(这个堆对象的内存地址,即指针)分配内存
实例说明一切
public class czTest {
public static void main(String[] args) {
String str1 = new String("Timo");
String str2 = "Timo";
String str3 = new String("Timo");
System.out.println(str1 == str2);
System.out.println(str1.equals(str3));
System.out.println(str3 == str2);
}
}
问题:(1)代码的执行过程?分别写出。(2)写出输出结果。
解析:
1.程序执行到"String str1 = new String(“Timo”)“时,首先在String常量池中查找有没有字符常量“Timo”。因为没有所以创建“Timo”对象,当执行new String(“Timo”)时,则在Java的堆中创建一个”Timo”对象,而str1是该对象的引用,因此共计创建2个对象。
2. 执行到"String str2 = “Timo”",首先在String常量池中查找有没有字符串常量“Timo",有则直接将str2作为String常量池中“Timo”的一个引用,当你重新声明一个String型变量为“Timo”时,将使用串池里原来的那个“Timo",而不用重新分配内存,也就是说,str1与str2将会指向同一块内存,因此,此时没有创建任何对象。
3. 执行到"String str3 = new String(“Timo”)",依次在String常量池中查找有没有字符串常量“Timo”,有则不进行再次创建,由于这里用了new关键字(有new就有对象),所以在Java堆中又创建了一个“Timo”对象(地址与第一句在堆中创建的地址不同),而str3则是这个对象的引用,因此执行此句时,创建了1个对象。
4. 执行到"System.out.println(str1 == str2)", “==”是判断对象的,由于str1指向的是Java堆中的“Timo”对象,而str2指向的是String常量池中的“Timo”对象,所以返回值为false。
5. 执行到"System.out.println(str1.equals(str3))",由于String类中的equals判断的是对象的内容而不是内存地址,由于所有内容都是Timo,所以返回值为true。
本文是从网上各个博客总结改动完成,以此作为个人随笔,时刻记忆,时刻理解。