随笔 - 0, 文章 - 11, 评论 - 0, 引用 - 0
数据加载中……

new String("value") 与 String string += "value" 的问题

环境: JDK6.0  Jad1.5.8(Java反编译工具)

先看测试代码与问题:

public class StringObjectValueStack {
    
    
/*
     * new String("value") 到底有几个对象?
     
*/
    
public void methodString () {
        String object 
= new String("value");
    }
    
    
/*
     * 为什么 String += "line"; 效率低下?
     
*/
    
public void methodManyString () {
        String manyObject 
= "" ;
        
for (int index = 0 ; index < 10 ; index ++) {
            manyObject 
+= "line" ;
        }
    }
    
    
/*
     * 为什么要用StringBuffer呢?
     
*/
    
public void methodStringBuffer () {
        StringBuffer stringBuffer 
= new StringBuffer() ;
        
for (int index = 0 ; index < 10 ; index ++) {
            stringBuffer.append(
"line") ;
        }
    }
    
    
/*
     * 为什么要用StringBuilder呢?
     
*/
    
public void methodStringBuilder () {
        StringBuilder stringBuilder 
= new StringBuilder() ;
        
for (int index = 0 ; index < 10 ; index ++) {
            stringBuilder.append(
"line") ;
        }
    }
}


看反编译结果:


public class StringObjectValueStack {

    
public StringObjectValueStack() {
    
//    0    0:aload_0         
    
//    1    1:invokespecial   #8   <Method void Object()>
    
//    2    4:return          
    }

    
public void methodString() {
        String object 
= new String("value");
    
//    0    0:new             #15  <Class String>   创建了一个实例对象 new String()
    
//    1    3:dup             
    
//    2    4:ldc1            #17  <String "value"> 创建了第二个实例对象
    
//    上面的 “value” 双引号的字符常量 第一次创建在 <字符常量缓冲区(Data Segment)> 中
    
//    下次再发现调用 "value" , 直接去 Data Segment 中拿值 , 不再新建
    
//    3    6:invokespecial   #19  <Method void String(String)>
    
//    4    9:astore_1        
    
//    5   10:return    
    
//    至此共创建了两个对象 
    }

    
public void methodManyString() {
        String manyObject 
= "";
    
//    0    0:ldc1            #25  <String "">
    
//    1    2:astore_1        
        for(int index = 0; index < 10; index++)
    
//*   2    3:iconst_0        
    
//*   3    4:istore_2        
    
//*   4    5:goto            31
            manyObject = (new StringBuilder(String.valueOf(manyObject))).append("line").toString();
    
//    5    8:new             #27  <Class StringBuilder> 在 循环体内 创建StringBuilder对象
    
//    虽然代码为 String += "line" ; 但编译器实际创建的还是StringBuilder对象来处理字符串
    
//    注意 JDK1.4 版本以前,编译器 实际调用的是StringBuffer, 直到 JDK1.5以后,底层用StringBuilder代替
    
//    6   11:dup             
    
//    7   12:aload_1         
    
//    8   13:invokestatic    #29  <Method String String.valueOf(Object)>
    
//    9   16:invokespecial   #33  <Method void StringBuilder(String)>
    
//   10   19:ldc1            #34  <String "line"> 
    
// 如果 <字符常量缓冲区(Data Segment)> 没有 "line" 的串对象,则创建了一个对象,以后每循环一次重复使用,不再新建
    
//   11   21:invokevirtual   #36  <Method StringBuilder StringBuilder.append(String)>
    
//   12   24:invokevirtual   #40  <Method String StringBuilder.toString()>
    
//   13   27:astore_1        

    
//   14   28:iinc            2  1
    
//   15   31:iload_2         
    
//   16   32:bipush          10
    
//   17   34:icmplt          8
    
//   18   37:return   
    
//   至此,使用 String string += "line" ; 在循环体中,循环多少次,就创建多少个全新的StringBuilder对象
    }

    
public void methodStringBuffer() {
        StringBuffer stringBuffer 
= new StringBuffer();
    
//    0    0:new             #48  <Class StringBuffer> 新建 StringBuffer 对象
    
//    1    3:dup             
    
//    2    4:invokespecial   #50  <Method void StringBuffer()>
    
//    3    7:astore_1        
        for(int index = 0; index < 10; index++)
    
//*   4    8:iconst_0        
    
//*   5    9:istore_2        
    
//*   6   10:goto            23
            stringBuffer.append("line"); // 只是调用 StringBuffer 的 append 方法 垒加 字符串 并未创建新对象
    
//    7   13:aload_1         
    
//    8   14:ldc1            #34  <String "line">
    
// 如果 <字符常量缓冲区(Data Segment)> 没有 "line" 的串对象,则创建了一个对象,以后每循环一次重复使用,不再新建
    
//    9   16:invokevirtual   #51  <Method StringBuffer StringBuffer.append(String)>
    
//   10   19:pop             

    
//   11   20:iinc            2  1
    
//   12   23:iload_2         
    
//   13   24:bipush          10
    
//   14   26:icmplt          13
    
//   15   29:return          
    
//   至次,只创建了一个StringBuffer对象
    }

    
public void methodStringBuilder() {
        StringBuilder stringBuilder 
= new StringBuilder();
    
//    0    0:new             #27  <Class StringBuilder>  新建 StringBuilder 对象
    
//    1    3:dup             
    
//    2    4:invokespecial   #57  <Method void StringBuilder()>
    
//    3    7:astore_1        
        for(int index = 0; index < 10; index++)
    
//*   4    8:iconst_0        
    
//*   5    9:istore_2        
    
//*   6   10:goto            23
            stringBuilder.append("line"); // 只是调用 StringBuilder 的 append 方法 垒加 字符串 并未创建新对象
    
//    7   13:aload_1         
    
//    8   14:ldc1            #34  <String "line">
    
// 如果 <字符常量缓冲区(Data Segment)> 没有 "line" 的串对象,则创建了一个对象,以后每循环一次重复使用,不再新建
    
//    9   16:invokevirtual   #36  <Method StringBuilder StringBuilder.append(String)>
    
//   10   19:pop             

    
//   11   20:iinc            2  1
    
//   12   23:iload_2         
    
//   13   24:bipush          10
    
//   14   26:icmplt          13
    
//   15   29:return      
   
//   至次,只创建了一个StringBuilder对象
    }
}

posted on 2014-05-13 16:52 00001000 阅读(216) 评论(0)  编辑  收藏 所属分类: Java 语言基础