Java String 字符池:
什么是java中的字符串池?下面我们通过几个程序片段解释说明。(对比结果)
1、使用new 创建java 字符串
String a1 = new String("Hello");//在堆内存中创建a1 对象,内容是Hello
String a2 = new String("Hello");//在堆内存中创建a2 对象,内容是Hello
System.out.println(a1 == a2); //false
System.out.println(a1.equals(a2));//true
2、使用引号 创建java字符串
String a3 = "Hello";//在栈内存中创建变量a3,内容是Hello;
String a4 = "Hello";//a4变量指向栈内存中国的Hello内容。所以a3、a4保持的地址值相同
System.out.println(a3 == a4); // true
System.out.println(a3.equals(a4));//true
3、引号创建字符串和new 创建字符串 作对比:
String a5 = "world";
String a6 = new String("world");
System.out.println(a5 == a6); // false
System.out.println(a5.equals(a6));// true
在上面三段代码中对比出了 java 字符串两种创建方式得区别;
“==” 操作符比较的是变量的值,无论是基本数据类型还是引用数据类型;
equals() 方法比较的是引用对象的内容值(前提 该类继承父类重写的或者自身重写了Object 类的equals方法)
String a3 = "Hello";
String a4 = "Hello";
为什么 a3 == a4 是true,因为使用引号创建字符串的时候是在栈内存中创建的并且是在字符池,如果字符池中存在相同内容的字符串值,则a4 指向 a3 的字符串对象引用不会再次创建;所以 a3 == a4 操作比较的都是同一个对象的地址值,故true;
String a1 = new String("Hello");
String a2 = new String("Hello");
而通过new 创建的相同内容的字符串 a1 == a2 操作比较后是false ,因为new 操作是在堆内存中创建的对象每次new操作都会在堆内存中重新开辟内存空间,两次new创建两个对象,两个对象的地址肯定不相同,所以 == 比较的结果是false,但是equals() 比较的是对象内容所以true(String类重写了equals方法)
结论:通过对比发现,使用 “引号”的方法创建字符串在一定程度上更加节省内存空间;
说到这里就要说明的是 java 字符串 字符串池的概念, 使用引号创建的java字符串默认都是在一个字符串池中,如果检测到存在相同内容的字符串,则将之前创建的对象的引用直接指向变量,如果没有相同的则在字符串池中创建独一无二的字符串,这一点和new创建的字符串有很大的不同,每new一次就开辟内存空间而不管内容是否相同,这样浪费java宝贵的内存空间;
下面要说的就是 将 new 创建的字符串也添加到字符串池中,使得更加节约内存空间;
要提到 String类中的 intern() 方法;
public String intern()
一个初始为空的字符串池,它由类 String
私有地维护。
当调用 intern 方法时,如果池已经包含一个等于此 String
对象的字符串(用 equals(Object)
方法确定),则返回池中的字符串。否则,将此 String
对象添加到池中,并返回此 String
对象的引用。
它遵循以下规则:对于任意两个字符串 s
和 t
,当且仅当 s.equals(t)
为 true
时,s.intern() == t.intern()
才为 true
。
所有字面值字符串和字符串赋值常量表达式都使用 intern 方法进行操作。字符串字面值在 Java Language Specification 的 §3.10.5 定义。
String a5 = "world";
String a6 = new String("world").intern(); // 通过intern方法将new 创建的字符串添加到字符串池中避免重复
System.out.println(a5 == a6); // true
System.out.println(a5.equals(a6)); // true
实例2:
String a1 = new String("Hello").intern();
String a2 = new String("Hello").intern();
System.out.println(a1 == a2); // true
System.out.println(a1.equals(a2)); // true
添加入 字符串地址池后 , == 操作对相同内容字符串比较的实际是同一对象的地址值,结果必然为true,而且节省内存空间;