欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 文化 > 深度解析new String(“abc”)的对象创建机制

深度解析new String(“abc”)的对象创建机制

2025/2/25 2:28:16 来源:https://blog.csdn.net/white_pure/article/details/145813292  浏览:    关键词:深度解析new String(“abc”)的对象创建机制

文章目录

    • 核心结论
    • 底层机制分步解析
    • 字节码实证分析

核心结论

创建对象数:2 个(当字符串常量池不存在 “abc” 时)。 第一个对象是"abc",它属于字符串字面量,因此编译时期会在字符串常量池中创建一个字符串对象,指向这个 “abc” 字符串字面量,而使用new的方式会在堆中创建一个字符串对象。

对象类型存储位置创建时机生命周期
字符串常量对象字符串常量池类加载阶段永久存在
普通字符串对象堆内存new 执行时跟随GC回收

底层机制分步解析

JDK8 中new String()源代码如下:

/*** Initializes a newly created {@code String} object so that it represents* the same sequence of characters as the argument; in other words, the* newly created string is a copy of the argument string. Unless an* explicit copy of {@code original} is needed, use of this constructor is* unnecessary since Strings are immutable.**/
public String(String original) {// 直接将原字符串的字符数组复制到新对象this.value = original.value;this.hash = original.hash; // 复用哈希值
}

文档注释大意:初始化新创建的String对象,使其表示与实参相同的字符序列。换句话说,用这个方法新创建的字符串是实参字符串的副本。除非需要显式复制形参的值,否则没有必要使用这个构造函数,因为字符串是不可变的。

由于String不可变性,此构造函数通常不必要使用,Java 13+已标记为@Deprecated

  • 首次出现的字面量,类加载时触发字符串驻留(intern)。
    // 类加载时自动执行
    String poolStr = "abc"; // 在常量池注册
    
  • 已存在的字面量,则直接引用常量池对象。
    String existStr = "abc"; // 不再创建新对象
    

字节码实证分析

创建一个测试类,用字节码观察,new String("abc")是否创建两个对象。

public class MainTest {public static void main(String[] args) {String s = new String("abc");}
}

使用javap -verbose命令进行反编译,得到以下内容:

// ...
Constant pool:
// ...#2 = Class              #18            // java/lang/String#3 = String             #19            // abc
// ...#18 = Utf8               java/lang/String#19 = Utf8               abc
// ...public static void main(java.lang.String[]);descriptor: ([Ljava/lang/String;)Vflags: ACC_PUBLIC, ACC_STATICCode:stack=3, locals=2, args_size=10: new           #2                  // class java/lang/String3: dup4: ldc           #3                  // String abc6: invokespecial #4                  // Method java/lang/String."<init>":(Ljava/lang/String;)V9: astore_1
// ...

Constant Pool中,#19存储这字符串字面量"abc"#3String Pool的字符串对象,它指向#19这个字符串字面量。在main方法中,0:行使用new #2在堆中创建一个字符串对象,并且使用ldc #3String Pool中的字符串对象作为String构造函数的参数。

  • ldc #3:将常量池中的"abc"对象压入操作数栈;
  • new #2:在堆内存分配新String对象;
  • invokespecial #4:调用String构造函数,复制原字符串的value数组;

所以能看到使用new String("abc")的方式创建字符串是创建两个对象。

JVM内存结构
value属性指向
字符串常量池
方法区/元空间
新String实例
堆内存
『abc』常量对象 (类加载时创建)
『abc』堆对象 (new执行时创建)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词