在学习String类型时,看到使用引用型变量作为方法的输入参数举例,于是查阅有关资料,大概对其做了了解。
一.首先要了解什么是字符串常量池(String Constant Pool)
字符串在java程序中被大量使用,为了避免每次都创建相同的字符串对象及内存分配,JVM内部对字符串对象的创建做了一定的优化,在Permanent Generation中专门有一块区域用来存储字符串常量池(一组指针指向Heap中的String对象的内存地址)。
程序运行时,可以通过String类的intern()方法动态地扩充字符串常量池。当调用 intern 方法时,如果池已经包含一个等于此String对象的字符串(用 equals(object)方法确定),则返回池中的字符串。否则,将此String 对象添加到池中,并返回此String对象的引用。所有字面值字符串和字符串赋值常量表达式都使用 intern 方法进行操作。
创建字符串对象的几种形式:
(1)通过new方式如String s = new String("aa")及string.intern()方法
(2)通过字面量的形式如String s = "aa"
(3)字面量+字面量如String s = "b" + "c"
(4)字面量+变量如String s1 = "d"; String s = "e"+s1
对于通过new方式创建的String对象,每次都会在Heap(堆)上创建一个新的实例,但是对于字符串字面量的形式,只有当字符串常量池中不存在相同对象时才会创建。
//关于堆Heap的解释
swift-algorithm-club/Heap at master · raywenderlich/swift-algorithm-club · GitHub
第二种方式不用说,相当于第一种方式中的字面量部分。
第三种和第四种方式会怎样创建字符串对象呢?
关于字符串常量池的问题可以看以下文章:
翻译:String类的intern()方法:一个初始为空的字符串池,它由类String独自维护。当调用 intern方法时,如果池已经包含一个等于此String对象的字符串(用equals(oject)方法确定),则返回池中的字符串。否则,将此String对象添加到池中,并返回此String对象(注意是常量池中的对象,不是堆中的对象)的引用。 对于任意两个字符串s和t,当且仅当s.equals(t)为true时,s.intern() == t.intern()才为true。所有字面值字符串和字符串赋值常量表达式都使用 intern方法进行操作。
自己用代码举了几个例子:
package com.company;
import com.sun.org.apache.xml.internal.utils.StringToStringTable;
public class Main {
public static void main(String[] args) {
String s1="hello";//创建String型引用变量s1,指向字符串常量池中的"hello"字符串。
String s2=new String("hello");//栈中创建s2引用变量,堆内存中创建"hello"字符串对象,并被s2指向。
System.out.println(s1 == s2);//false
String s3="h"+"ello";//"h"和"ello"合成为字符串常量"hello",先在字符串常量池中查找是否已有"hello"字符串对象,已有,不再重新创建对象
System.out.println(s1 == s3);//true
String s4="h"+new String("ello");//在堆中创建了"ello"对象,与"h"相加,返回新的字符串对象赋给s4,s4还指向堆中的字符串对象。
System.out.println(s1==s4);//false
System.out.println(s2==s4);//false
}
}
package com.company;
import com.sun.org.apache.xml.internal.utils.StringToStringTable;
public class Main {
public static void main(String[] args) {
String string1 = "hello";
String string2 = new String("hello");
String string3 = new String("hello");
System.out.println(string1 == string2.intern());//true
System.out.println(string2 == string3.intern());//false
}
}
记录自己学习java的历程
参考文章:
JDK1.8字符串常量池里存的是String对象还是引用? - 程序员曾奈斯 - 博客园