字符串常量池

引言

Java语言不要求常量一定要在编译期才能产生,也就是并非预置入Class文件中常量池的内容才能进入方法区的运行时常量池,程序运行期间也可以将常量放入池中。

设计字符串常量池的原因

字符串在java程序中被大量使用,为了避免每次都创建相同的字符串对象及内存分配,JVM内部对字符串对象的创建做了一定的优化,在Permanent Generation中专门有一块区域用来存储字符串常量池(一组指针指向Heap中的String对象的内存地址)。

字符串所在的内存区域

两种内存区域:常量池、堆

String str1 = "helloworld"; //存在于常量池中
String str2 = new String("helloworld"); // 'helloworld'存在于常量池中,String对象存在于堆中
String str3 = str1 + "world"; // 有字符串引用时,在堆中建立一个String对象将引用返回

String中intern的方法

当调用 intern 方法时,如果池已经包含一个等于此String对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并且返回此 String对象的引用。

public static void main(String[] args) {
        String str1 = "a";
        String str2 = "b";
        String str3 = "ab";
        String str4 = str1 + str2;
        String str5 = new String("ab");
        
        System.out.println(str5 == str3);
        System.out.println(str5.intern() == str3);
        System.out.println(str5.intern() == str4);
}

结果:false, true, false

解析原因:1、一个存在于常量池中,一个存在于堆中对象地址不同返回false

     2、str5执行intern方法去常量池中判断有没有和''ab''字符串equals的字符串,一看有就是str3返回str3的引用,此时再==时返回true

     3、str5执行intern方法去常量池中判断有没有和''ab''字符串equals的字符串,一看有就是str3返回str3的引用,此时判断str3和str4是否==,我们知道str3存在于常量池,str4存在于堆中地址不同返回false

str1,str2,str3在JVM编译期就已经存在了位于字符串常量池中,而str4和str5是在程序运行期才存在的位于堆中

原文地址:https://www.cnblogs.com/BINGJJFLY/p/7605943.html