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维护了一个字符串的常量池,当用String a = "hello"这种方式时,首先创建一个String类型的引用a,然后到常量池中需找是否有等于"hello"的字符串,有的话另a指向它,没有则在常量池中新建,然后a指向它。所以上例中,b直接指向这个常量,a和b在内存中是同一个对象,所以a==b为true。
    而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行的结果,你能给出原因么?
 
posted @ 2016-01-26 09:39  进击的璐璐  阅读(1797)  评论(0编辑  收藏  举报