根据Java运行时数据区进行划分,自己总结的的一个模型

Java 创建内存表 java编程简易内存池_Java 创建内存表

基本数据类型中实现了常量池的:

Byte,Short,Integer,Long,Character,Boolean

未实现常量池的:

Double,Float

String对象的intern()方法

查看常量池中是否有该字符串,有则返回该字符串引用,否则,添加在常量池中添加该字符串。

字符串拼接用+

  1. 使用引号包含文本的方式创建的String对象之间用+连接产生的新对象会加入字符串常量池。
  2. new方式创建的对象用+连接产生的不会。
String str1 = "str";
  String str2 = "ing";
  
  String str3 = "str" + "ing";
  String str4 = str1 + str2;
  System.out.println(str3 == str4);//false
  
  String str5 = "string";
  System.out.println(str3 == str5);//true

特例1:
A和B都是常量,值是固定的,因此s的值也是固定的,它在类被编译时就已经确定了。也就是说:String s=A+B; 等同于:String s=“ab”+“cd”;

public static final String A = "ab"; // 常量A
public static final String B = "cd"; // 常量B
public static void main(String[] args) {
     String s = A + B;  // 将两个常量用+连接对s进行初始化 
     String t = "abcd";   
    if (s == t) {   
         System.out.println("s等于t,它们是同一个对象");   
     } else {   
         System.out.println("s不等于t,它们不是同一个对象");   
     }   
 } 
s等于t,它们是同一个对象

特例2:
A和B虽然被定义为常量,但是它们都没有马上被赋值。在运算出s的值之前,他们何时被赋值,以及被赋予什么样的值,都是个变数。因此A和B在被赋值之前,性质类似于一个变量。那么s就不能在编译期被确定,而只能在运行时被创建了。

public static final String A; // 常量A
public static final String B;    // 常量B
static {   
     A = "ab";   
     B = "cd";   
 }   
 public static void main(String[] args) {   
    // 将两个常量用+连接对s进行初始化   
     String s = A + B;   
     String t = "abcd";   
    if (s == t) {   
         System.out.println("s等于t,它们是同一个对象");   
     } else {   
         System.out.println("s不等于t,它们不是同一个对象");   
     }   
 } 
s不等于t,它们不是同一个对象

丰富的例子:

public class Test {
 public static void main(String[] args) {   
      String hello = "Hello", lo = "lo";
      System.out.println((hello == "Hello") + " ");
      System.out.println((Other.hello == hello) + " ");
      System.out.println((other.Other.hello == hello) + " ");
      System.out.println((hello == ("Hel"+"lo")) + " ");
      System.out.println((hello == ("Hel"+lo)) + " ");
      System.out.println(hello == ("Hel"+lo).intern());
 }   
}
class Other { static String hello = "Hello"; }
package other;
public class Other { public static String hello = "Hello"; }
true true true true false true
在同包同类下,引用自同一String对象.
在同包不同类下,引用自同一String对象.
在不同包不同类下,依然引用自同一String对象.
在编译成.class时能够识别为同一字符串的,自动优化成常量,引用自同一String对象.
在运行时创建的字符串具有独立的内存地址,所以不引用自同一String对象.