String:intern()是一个本地方法,它的作用是如果字符串常量池中已经包含一个等于此String对象的字符串,则返回代表池中这个字符串的String对象的引用;否则,会将此String对象包含的字符串添加到常量池中,并且返回此String对象的引用。
public class InternDemo {
public static void main(String[] args) {
String a = new StringBuffer("chen").append("fei").toString();
System.out.println(a);
System.out.println(a.intern());
System.out.println(a == a.intern());
System.out.println("----------");
String b = new StringBuffer("ja").append("va").toString();
System.out.println(b);
System.out.println(b.intern());
System.out.println(b == b.intern());
}
}输出结果:
chenfei
chenfei
true
----------
java
java
false按照代码结果,Java字符串答案为false必然是两个不同的java,那另外一个java字符串如何加载进来的?
有一个初始化的Java字符串(JDK出娘胎自带的),在加载sun.misc.Version这个类的时候进入常量池。
System代码解析 System -> initializeSystemClass() -> Version
package java.lang;
public final class System {
/* register the natives via the static initializer.
*
* VM will invoke the initializeSystemClass method to complete
* the initialization for this class separated from clinit.
* Note that to use properties set by the VM, see the constraints
* described in the initializeSystemClass method.
*/
private static native void registerNatives();
static {
registerNatives();
}
//本地方法registerNatives()将会调用initializeSystemClass()
private static void initializeSystemClass() {
...
sun.misc.Version.init();
...
}
...
}
package sun.misc;
//反编译后的代码
public class Version {
private static final String launcher_name = "java";
...
}
类加载器和rt.jar - 根加载器提前部署加载rt.jar
sun.misc.Version类会在JDK类库的初始化过程中被加载并初始化,而在初始化时它需要对静态常量字段根据指定的常量值(ConstantValue〉做默认初始化,此时被sun.misc.Version.launcher静态常量字段所引用的”java”字符串字面量就被intern到HotSpot VM的字符串常量池——StringTable里了。