最近在通过阅读《深入理解Java虚拟机——JVM特性与最佳实践》这本书时,发现书中在介绍运行时常量池中有这样一段话:
“运行时常量池相对于Class文件常量池的另外一个重要特征是具备动态性,Java语言并要求常量一定只有编译期才能产生,也就是并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中,这种特性被开发人员利用得比较多得是String类的intern()方法”
intern()方法在jdk的文档中是这样描述的:“When the intern method is invoked, if the pool already contains a string equal to this {@code String} object as determined by the {@link #equals(Object)} method, then the string from the pool is returned. Otherwise, this {@code String} object is added to the pool and a reference to this {@code String} object is returned.”简而言之,如果池中有该变量即引用,没有就创建。
在验证之前,要了解一下“==” 和 equals方法的区别:
Java有八大基础类型分别是:byte, short, char, int, long, float, double, boolean
上述数据类型没有equals方法,==方法就是比较数据的值是否相等
而对于其他复合数据类型而言,==方法是比较两个对象的引用是否相等,也就是比较两个对象的地址是否相等(是不是同一个对象),众所周知所有java类型都有个公共的爹,Object类,而在该类中也定义了一个equals方法
public boolean equals(Object obj) { return (this == obj); }
可以看到该方法就是调用了==方法即比较两个对象的地址值是否相等,String类中对该类进行了重写,
public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }在该方法中,首先判断是否为同一个对象,如果不是同一个对象,那么判断是否为String类型,如果不为String类型就返回false,如果为String类型将其转换为基本数据类型char,通过基本数据类型的比较为值比较来比较两个String对象的值是否相等。
下面的代码可以验证:
String str0 = new String("a"); String str1 = str0.intern(); String str2 = "a"; String str3 = "a"; System.out.println(str1 == str0);//false System.out.println(str2 == str0);//false System.out.println(str2 == str1);//true System.out.println(str3 == str2);//true
以上对象的比较如果通过equals方法返回值都为true