栈(stack):主要保存基本类型(或者叫内置类型)(char、byte、short、int、long、double、float、boolean)和对象的引用,数据可以共享,速度仅次于寄存器(register),快于堆。
方法区(method area):static final 修饰的成员变量都存储于方法区中,如常量池。
堆(heap):用于存储对象实例及数组。
方法区:
以String 类型来举例:
1 String s1="abc";2 String s2="abc";3 String s3=new String("abc");4 System.out.println("s1和s2 引用地址是否相同:"+(s1 ==s2)); //true5 System.out.println("s1和s2 值是否相同:"+s1.equals(s2)); //true6 System.out.println("s1和s3 引用地址是否相同:"+(s1 ==s3)); //false7 System.out.println("s1和s3 值是否相同:"+s1.equals(s3)); //true
内存结构图如下:
s1 和 s2 地址引用值相等,说明 s1 和 s2 引用的是同一个对象的地址,s3 与 s1 地址引用不等,说明 s3 与其他两个引用的不是同一个地址。
java为了避免产生大量的String对象,设计了一个字符串常量池(存在内存中的方法区里)。工作原理是这样,创建一个字符串时,JVM首先会检查字符串常量池中是否有值相等的字符串,如果有,则不再创建,直接返回该字符串的引用地址,如果没有,则创建,然后放到字符串常量池中,并返回新创建的字符串的引用地址,所以上面s1==s2结果为true。
而 s3 不同的是,JVM首先是在字符串常量池中找 "abc" 字符串,如果没有则创建字符串常量,如果有则不需要创建;当遇到 new 时,还会在堆内存里面创建一个新的 String 对象,存储 “abc” ,并将堆内存上String 对象引用的地址返回,所以 s3 与 s1 、s2 引用的不是同一个字符串地址。
版权声明:本文版权归作者所有,欢迎转载,但请注明出处。