Java String深度探幽

Java String深度探幽

  • 01. 概述
  • 02. 内存分析
    • 2.1 常量赋值
    • 2.2 new对象
    • 2.3 字符串常量拼接操作(+)
    • 2.4 非常量字符串拼接(+)
  • 04. intern方法
  • 05. 总结

01. 概述

  • 类定义
    public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence {
        private final char value[];
        private int hash; // Default to 0
    }
    
  • 特点
    01)final修饰的类,作用:KV键的关键点。
    02)char数组来保存字符串值。
    03)对其实例任何操作都不会影响到原实例,所有改变都会创建新实例对象。
  • intern方法
    频繁创建对象不仅耗费堆空间,而且增加gc负重,为了提升性能,调用intern方法将String实例加入到常量池。

02. 内存分析

2.1 常量赋值

  • 代码
    String str = "hi,nice to meet you!";
    
  • 内存分析
    Java String深度探幽_第1张图片
  • 分析
    对于常量赋值来说,变量str始终指向字符串常量池的字符串。

2.2 new对象

  • 代码
    String str = new String("hi,nice to meet you!");
    
  • 源码
    public String(String original) {
    	this.value = original.value;
    	this.hash = original.hash;
    }
    
  • 内存分析
    Java String深度探幽_第2张图片
  • 分析
    01)生成了两个对象,分别是"hello world"和new String(“hello world”)。
    02)如果"hello world"已存在于运行时常量池中,那么不会重复创建。
    03)new String(“hello world”)时,将常量池中的"hello world"复制一份放到heap中,执行new操作,并且把heap中新创建对象的引用交给str持有。

2.3 字符串常量拼接操作(+)

  • 代码
String str = "hi" + "," + "nice to meet you!"; 
final String str= "hi" + "," + "nice to meet you!"; 
  • 内存分析
    Java String深度探幽_第3张图片
  • 分析
    01)JIT编译时,创建"hello"、"-"和"world"实例并且加载到运行是常量池中。
    02)JIT编译优化时,创建一个StringBuilder对象进行拼接,然后调用通过toString方法创建实例,并且载入到常量池中。
    03)运行时,从运行时常量池读取该实例。

2.4 非常量字符串拼接(+)

  • 代码
    String str = new String("hi") + "," + "nice to meet you!";
    
  • 内存分析
    Java String深度探幽_第4张图片
  • 分析
    01)JIT编译时,创建"hello"和"word"实例,并且加载到常量池中。
    02)运行期间,拷贝常量池对象创建new String(“hello”)实例。
    03)拼接时,创建StringBuilder对象进行拼接,然后toString方法生成String(“helloword”)对象存储到堆空间中,注意:"helloword"不会放入常量池中。

04. intern方法

频繁创建对象不仅耗费堆空间,而且增加gc负重,为了提升性能,调用intern方法将String实例加入到常量池。

05. 总结

  • 直接字符串常量赋值,该字符串常量将被载入到运行时常量池中。
  • new出来的字符串存放在堆里面。
  • 对字符串进行拼接操作,也就是做"+"运算的时候,分2种情况:
    01)表达式右边是字符串常量,运算结果存放运行时常量池中。
    02)表达式右边如果存在字符串引用(即对象的句柄),运算结果存放在堆空间。

你可能感兴趣的:(Java)