String类对象的创建与字符串常量池的“神秘交易”-灵析社区

英勇黄铜

创建对象内的“那些事”

话不多说,直接上代码:

public static void main(String[] args) {
    String s1 = "hello";
    String s2 = "hello";
    String s3 = new String("hello");
    String s4 = new String("hello");
    System.out.println(s1 == s2); // true
    System.out.println(s1 == s3); // false
    System.out.println(s3 == s4); // false
}

上面这个代码我们发现创建的 String 对象的方式类似,但是结果 s1 和 s2 是同一个对象,但 s3 和 s4 却却不是?

这就是要深究到 java 中的常量池了。在 java 中,“hello”,“1234” 等常量经常被频繁使用,java 为了让程序运行的速度更加快,跟节省内存,就为 8 种基本类型和 String 类提供了常量池。

java 中引入了:

Class 文件常量池:每个 Java 源文件编译后生成的  Class 文件中会保存当前类中的字面常量以及符号信息

运行时常量池:在. Class 文件被加载时,Class 文件中的常量池被加载到内存中称为运行时常量池,运行时常量池每个类都会有一份

"池" 是编程中的一种常见的, 重要的提升效率的方式, 我们会在遇到各种 "内存池", "线程池", "数据库连接池"

字符串常量池

字符串常量池在 JVM 中是一个 StringTable 类,实际是一固定大小的 HashTable,它是一种高效查找的数据结构,在不同的 JDK 版本下字符串常量池的位置以及默认大小是不同的:

对 String 对象创建的具体分析

直接使用字符串常量进行赋值

public static void main(String[] args) {
        String str1 ="hello";
        String str2 ="hello";
        System.out.println(str1 == str2);
    }

这里直接通过画图分析:

通过 new 创建 String 对象

public static void main(String[] args) {
        String str1 = new String("hello");
        String str2 = "hello";
        System.out.println(str1 == str2);
    }

这里我们得到一个结论:只要是 new 出来的对象,就是唯一的

这里我们可以知道:使用常量串创建 String 类型对象的效率更高,更节省空间。用户也可以将创建的字符串对象通过 intern 方式添加进字符串常量池中

intern 方法

intern 方法的作用就是将创建的 String 对象添加到常量池中、

public static void main(String[] args) {
    char[] ch = new char[]{'a', 'b', 'c'};
    String s1 = new String(ch); // s1对象并不在常量池中
    //s1.intern(); 调用之后,会将s1对象的引用放入到常量池中
    String s2 = "abc"; // "abc" 在常量池中存在了,s2创建时直接用常量池中"abc"的引用
    System.out.println(s1 == s2);
}

放开前返回的是 false,放开后返回 true:

使用方法前,常量池中没有 “abc” ,导致  str2  自己重新创建了一份  “abc”

使用方法后,常量池中有了 “abc” , str2  直接拿过来用就可以了

阅读量:2026

点赞量:0

收藏量:0