关于字符串的一系列问题

首先我们需要知道String是一个不可变的对象,任何看似会修改其内容的方法,实际上都是创建了一个新的String对象。
String的不可变性会为程序带来效率问题,因此JVM会将新创建的String对象放入一个常量池中,待下次用到相同String对象时,编译器会从常量池中取得,而不是重新new一个String对象。
看下面的面试题:
String s = new String("abcdefg");这一语句创建了几个String对象?
分析:当程序运行时,会首先创建一个字符串对象"abcdefg",并将其放入常量池中。当执行new操作时,又会在堆中创建一个String对象,该对象是对常量池中"abcdefg"串的一个拷贝。而String s仅仅是声明了一个指向字符串类型的引用,并没有创建任何字符串对象。
因此,答案是2个。

另外,关于String,StringBuilder和StringBuffer三者之间的区别也是面试中经常遇到的问题。
String与StringBuilder的区别主要体现在做字符串连接操作的效率上。
先看String的连接操作,代码如下:
public   class  StringConnection {

    
/**
     * 
@param  args
     
*/
    
public   static   void  main(String[] args) {
        
//  TODO Auto-generated method stub
        String str  =   " my " ;
        String introduction 
=  str  +   "  name "   +   "  is "   +   "  cgw. " ;
        System.out.println(introduction);
    }

}
再使用javap命令将class文件进行反编译得到:
Compiled from  " StringConnection.java "
public   class  StringConnection  extends  java.lang.Object{
public  StringConnection();
  Code:
   
0 :   aload_0
   
1 :   invokespecial   # 8 // Method java/lang/Object."<init>":()V
    4 :    return

public   static   void  main(java.lang.String[]);
  Code:
   
0 :   ldc     # 16 // String my
    2 :   astore_1
   
3 :    new      # 18 // class java/lang/StringBuilder
    6 :   dup
   
7 :   aload_1
   
8 :   invokestatic    # 20 // Method java/lang/String.valueOf:(Ljava/lang/Objec
t;)Ljava / lang / String;
   
11 :  invokespecial   # 26 // Method java/lang/StringBuilder."<init>":(Ljava/la
ng / String;)V
   
14 :  ldc     # 29 // String  name
    16 :  invokevirtual   # 31 // Method java/lang/StringBuilder.append:(Ljava/lang
/ String;)Ljava / lang / StringBuilder;
   
19 :  ldc     # 35 // String  is
    21 :  invokevirtual   # 31 // Method java/lang/StringBuilder.append:(Ljava/lang
/ String;)Ljava / lang / StringBuilder;
   
24 :  ldc     # 37 // String  cgw.
    26 :  invokevirtual   # 31 // Method java/lang/StringBuilder.append:(Ljava/lang
/ String;)Ljava / lang / StringBuilder;
   
29 :  invokevirtual   # 39 // Method java/lang/StringBuilder.toString:()Ljava/l
ang / String;
   
32 :  astore_2
   
33 :  getstatic       # 43 // Field java/lang/System.out:Ljava/io/PrintStream;
    36 :  aload_2
   
37 :  invokevirtual   # 49 // Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
   
40 :   return

}
我们可以看到,在main方法内的第3行,JVM为我们new了一个StringBuilder对象,然后调用append方法进行字符串的连接,既然编译器能为我们自动选择性能较优的StringBuilder,那我们为什么不能随意使用String呢?再看看下面的代码:
public   class  StringBuilderConnection {

    
/**
     * 使用String进行字符串连接
     * 
@param  fields
     * 
@return
     
*/
    
public  String StringConnection(String[] fields) {
        String result 
=   "" ;
        
for ( int  i = 0 ; i < fields.length; i ++ ) {
            result 
+=  fields[i];
        }
        
return  result;
    }
    
    
/**
     * 使用StringBuilder进行字符串连接
     * 
@param  fields
     * 
@return
     
*/
    
public  String SBConnection(String[] fields) {
        StringBuilder result 
=   new  StringBuilder();
        
for ( int  i = 0 ; i < fields.length; i ++ ) {
            result.append(fields[i]);
        }
        
return  result.toString();
    }
}
同样进行反编译得到:
Compiled from  " StringBuilderConnection.java "
public   class  StringBuilderConnection  extends  java.lang.Object{
public  StringBuilderConnection();
  Code:
   
0 :   aload_0
   
1 :   invokespecial   # 8 // Method java/lang/Object."<init>":()V
    4 :    return

public  java.lang.String StringConnection(java.lang.String[]);
  Code:
   
0 :   ldc     # 16 // String
    2 :   astore_2
   
3 :   iconst_0
   
4 :   istore_3
   
5 :    goto      32
   
8 :    new      # 18 // class java/lang/StringBuilder
    11 :  dup
   
12 :  aload_2
   
13 :  invokestatic    # 20 // Method java/lang/String.valueOf:(Ljava/lang/Objec
t;)Ljava / lang / String;
   
16 :  invokespecial   # 26 // Method java/lang/StringBuilder."<init>":(Ljava/la
ng / String;)V
   
19 :  aload_1
   
20 :  iload_3
   
21 :  aaload
   
22 :  invokevirtual   # 29 // Method java/lang/StringBuilder.append:(Ljava/lang
/ String;)Ljava / lang / StringBuilder;
   
25 :  invokevirtual   # 33 // Method java/lang/StringBuilder.toString:()Ljava/l
ang / String;
   
28 :  astore_2
   
29 :  iinc     3 1
   
32 :  iload_3
   
33 :  aload_1
   
34 :  arraylength
   
35 :  if_icmplt        8
   
38 :  aload_2
   
39 :  areturn

public  java.lang.String SBConnection(java.lang.String[]);
  Code:
   
0 :    new      # 18 // class java/lang/StringBuilder
    3 :   dup
   
4 :   invokespecial   # 45 // Method java/lang/StringBuilder."<init>":()V
    7 :   astore_2
   
8 :   iconst_0
   
9 :   istore_3
   
10 :   goto      24
   
13 :  aload_2
   
14 :  aload_1
   
15 :  iload_3
   
16 :  aaload
   
17 :  invokevirtual   # 29 // Method java/lang/StringBuilder.append:(Ljava/lang
/ String;)Ljava / lang / StringBuilder;
   
20 :  pop
   
21 :  iinc     3 1
   
24 :  iload_3
   
25 :  aload_1
   
26 :  arraylength
   
27 :  if_icmplt        13
   
30 :  aload_2
   
31 :  invokevirtual   # 33 // Method java/lang/StringBuilder.toString:()Ljava/l
ang / String;
   
34 :  areturn

}
我们可以看到,在StringConnection方法中,第5行和第35行构成了一个循环,而StringBuilder的创建操作是在循环体的内部进行的,因此该方法会导致创建多个StringBuilder对象。而在SBConnection方法中,StringBuilder的创建操作是在循环体外,至始至终都只会创建一个StringBuilder对象,效率的高低显而易见。
通过以上的分析,我们可以得知,当字符串的操作比较简单时,你可以信赖编译器,使用String,它会为你进行合理的优化。但当如果涉及到循环等复杂操作时,你就应该使用StringBuilder啦。

至于StringBuilder与StringBuffer,两者基本相同,只是StringBuffer的线程安全特性会造成额外的开销,因此StringBuilder的效率要略高于StringBuffer。

转载于:https://www.cnblogs.com/chenguanwei/archive/2009/10/14/1582890.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值