Java中String的实现与应用
public final class String implements java.io.Serializable, Comparable<String>, CharSequence {
privatefinalchar value[];
privateint hash; }
String其实是对一个char数组的封装。提供了各种操作方法。值得注意的是这个数组的final的,也就是这个引用是不可变的。注意是引用,数组中每一项的值理论上是可以改变的,比如通过反射,但是不推荐这么做。
关于String有一些有趣的地方:
package terry.java.base; publicclass StringTest { publicstaticvoid main(String[] args) { String a = "hello"; String b = "hello"; String newA = new String("hello"); String newB = new String("hello"); System.out.println("****** Testing Object == ******"); System.out.println("a==b ? :" + (a==b)); System.out.println("newA==newB ? :" +(newA==newB)); System.out.println("a==newA ? :" + (a==newA)); System.out.println("***** Testing String Object intern method******"); System.out.println("a.intern()==b.intern() ? : " + (a.intern()==b.intern())); System.out.println("newA.intern()==newB.intern() ? :" + (newA.intern()==newB.intern())); System.out.println("a.intern()==newA.intern() ? :" + (a.intern()==newA.intern())); System.out.println("a=a.intern() ? :" + (a==a.intern())); System.out.println("newA==newA.intern() ? : " + (newA==newA.intern())); System.out.println("****** Testing String Object equals method******"); System.out.println("equals() method :" + a.equals(newA)); String c = "hel"; String d = "lo"; final String finalc = "hel"; final String finalgetc = getc(); System.out.println("****** Testing Object splice ******");2 System.out.println("a==\"hel\"+\"lo\" ? :" + (a=="hel"+"lo")); System.out.println("a==c+d ? : " + (a==c+d)); System.out.println("a==c+\"lo\" ? : " + (a==c+"lo")); System.out.println("a==finalc+\"lo\" ? :" + (a==finalc+"lo")); System.out.println("a==finalgetc+\"lo\" ? :" + (a==finalgetc+"lo")); } privatestatic String getc(){ return"hel"; } }
输出:
****** Testing Object == ****** a==b ? :true newA==newB ? :false a==newA ? :false ***** Testing String Object intern method****** a.intern()==b.intern() ? : true newA.intern()==newB.intern() ? :true a.intern()==newA.intern() ? :true a==a.intern() ? :true newA==newA.intern() ? : false ****** Testing String Object equals method****** equals() method :true ****** Testing Object splice****** a=="hel"+"lo" ? :true a==c+d ? : false a==c+"lo" ? : false a==finalc+"lo" ? :true a==finalgetc+"lo" ? :false
而String newA = new String("hello")这种方方式,会在堆内存中新建一个字符串对象,所以与a、b所指向的常量池中对象是不同对象。==为false。
接下来出现了一个不太常用的intern方法。这个方法的作用是,在常量池中查找是否有与当前字符串值相同的常量,如果没有,则新建常量并返回常量引用,但当前引用不变;如果有直接返回引用。所以上例中newA.intern()返回了常量池中”hello“的引用与a、b为相同对象,但newA在intern后仍指向对中的那个对象,所以newA==newA.intern()不成立。这个方法对于重复率高的字符串可以提高内存利用率,减轻内存负担。但是常量表中的对象,一般不会被回收,会随着堆积占用越来越多的内存。所以要根据实际情况权衡利弊。
再往下,Java中罕见的运算符重载,是+和+=对String的重载,在使用中也有些需要注意的地方。类似"a" + "b"这样字符串常量用+连接的情形,在编译期间,JVM就将+连接优化为连接后的值。同时fianl修饰的已赋值String变量,在编译期同样被一个常量,保存到常量池中。所以上面输出中的14/17行的结果就不足为奇了。
在15行的结果中,JVM对于变量间的+操作,是转换为StringBuilder的append操作,所以产生了新的堆内对象。所以为false。
第18行的结果,你能给出原因么?
![](https://images2015.cnblogs.com/blog/886074/201601/886074-20160126093918051-1041461108.png)