posts - 3,  comments - 7,  trackbacks - 0
题目:String s = new String("xyz"); 这么一题简单的java笔试题,对于java新手来说可能会做错,看只要是PAPER,看一遍,听人家讲一遍就知道了。
问:执行这一语句,一共创建了几个String对象?
答:2个,1个在String池中,一个在堆内存中。

但其实这题目具有很大的灵活度,如果不真正理解String的运作机制,换个样子就有可能把PAPER难住了。
String s1 = "xyz"; String s2 = "x"+"yz"; String s3 = "x"+new String("yz"); String s4=new String("xyz");
如果说s1==s2,那s1为什么!=s3呢?为什么s1!=s4呢?

String类是java中一个比较特殊的类,与其相关的还有java中仅有的两个内置重载操作符:"+"和"+="。
String类对象是不可变的,而StringBuffer & String Builder类对象是可变的;String类重写了equals方法,而StringBuffer & String Builder类却没有重写。

拿操作符"+"来说,其两边的操作元类型无非就5种情况(注意操作符的左结合性):
1、两个操作元都是基本类型(原始类型):效果是重载前的算术运算
2、两个操作元都是非String类型的引用类型:编译无法通过,不支持
3、两个操作元都是String类型:重载操作
4、一个是String类型,一个是基本类型:重载操作
5、一个是String类型,一个是引用类型:重载操作

其实对于3、4两种情况,由于String类型的特殊性,编译器会在编译时做一些特殊处理,所以情况会变得稍微复杂一点。
 1public class StringTest
 2{
 3    public static void main(String[] args)
 4    {
 5        //1.操作符两边都是基本类型(原始类型),则"+"操作符代表算术运算
 6        //2.操作符两边都是非String类型的引用类型,重载操作不支持,编译错误
 7        //3.操作符两边都是String类型
 8        String s1 = new String("hello");
 9        String s2 = new String("world");
10        String s3 = s1+s2; //重载操作是通过StringBuilder实现的
11        
12        //4.操作符一边是基本类型(原始类型)
13        int i = 2008;
14        String s4 = new String("beijing");
15        String s5 = s4+i; //重载操作是通过StringBuilder实现的,
16        //对于基本类型也并不是转化成String字符串再进行连接
17
18        //5.操作符一边是引用类型
19        Integer in = new Integer(2008);
20        String s6 = s4+in; //重载操作是通过StringBuilder实现的,
21        //对于引用类型in,通过in.toString()方法返回字符串,再进行连接
22
23        //6.操作符都是String类型,且都是编译时可计算的
24        String s7 = "hello"+"world"//编译后就确定了s7取值,并不需要等到运行时
25        System.out.println(s3==s7); //false, s3指向StringBuilder返回的,指向堆内存的新String对象,s7则指向String池
26
27        //7.操作符一边是基本类型(原始类型)
28        String s8 = "beijing"+2008//编译后就确定了s8取值,并不需要等到运行时
29        System.out.println(s5==s8); //false, s5指向StringBuilder返回的,指向堆内存的新String对象,s8则指向String池
30
31        String s9 = "beijing"+i; //编译时无法计算出取值,s9的结果是指向堆内存
32        System.out.println(s8==s9); //false, s9指向的是堆内存,而s8指向String池
33        s7 += " blogjava"//编译时无法计算出取值,s7的结果是指向堆内存
34        System.out.println(s7=="helloworld blogjava".intern()); //false, s7指向的是堆内存
35    }

36}

37

查看反编译后的源代码或许更能理解String的运作机制:
Compiled from "StringTest.java"
public class StringTest extends java.lang.Object{
public StringTest();
  Code:
   
0:    aload_0
   
1:    invokespecial    #1//Method java/lang/Object."<init>":()V
   4:    return

public static void main(java.lang.String[]);
  Code:
   
0:    new    #2//class java/lang/String
   3:    dup
   
4:    ldc    #3//String hello
   6:    invokespecial    #4//Method java/lang/String."<init>":(Ljava/lang/String;)V
   9:    astore_1
   
10:    new    #2//class java/lang/String
   13:    dup
   
14:    ldc    #5//String world
   16:    invokespecial    #4//Method java/lang/String."<init>":(Ljava/lang/String;)V
   19:    astore_2
   
20:    new    #6//class java/lang/StringBuilder
   23:    dup
   
24:    invokespecial    #7//Method java/lang/StringBuilder."<init>":()V
   27:    aload_1
   
28:    invokevirtual    #8//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   31:    aload_2
   
32:    invokevirtual    #8//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   35:    invokevirtual    #9//Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   38:    astore_3
   
39:    sipush    2008
   
42:    istore    4
   
44:    new    #2//class java/lang/String
   47:    dup
   
48:    ldc    #10//String beijing
   50:    invokespecial    #4//Method java/lang/String."<init>":(Ljava/lang/String;)V
   53:    astore    5
   
55:    new    #6//class java/lang/StringBuilder
   58:    dup
   
59:    invokespecial    #7//Method java/lang/StringBuilder."<init>":()V
   62:    aload    5
   
64:    invokevirtual    #8//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   67:    iload    4
   
69:    invokevirtual    #11//Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
   72:    invokevirtual    #9//Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   75:    astore    6
   
77:    new    #12//class java/lang/Integer
   80:    dup
   
81:    sipush    2008
   
84:    invokespecial    #13//Method java/lang/Integer."<init>":(I)V
   87:    astore    7
   
89:    new    #6//class java/lang/StringBuilder
   92:    dup
   
93:    invokespecial    #7//Method java/lang/StringBuilder."<init>":()V
   96:    aload    5
   
98:    invokevirtual    #8//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   101:    aload    7
   
103:    invokevirtual    #14//Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
   106:    invokevirtual    #9//Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   109:    astore    8
   
111:    ldc    #15//String helloworld
   113:    astore    9
   
115:    getstatic    #16//Field java/lang/System.out:Ljava/io/PrintStream;
   118:    aload_3
   
119:    aload    9
   
121:    if_acmpne    128
   
124:    iconst_1
   
125:    goto    129
   
128:    iconst_0
   
129:    invokevirtual    #17//Method java/io/PrintStream.println:(Z)V
   132:    ldc    #18//String beijing2008
   134:    astore    10
   
136:    getstatic    #16//Field java/lang/System.out:Ljava/io/PrintStream;
   139:    aload    6
   
141:    aload    10
   
143:    if_acmpne    150
   
146:    iconst_1
   
147:    goto    151
   
150:    iconst_0
   
151:    invokevirtual    #17//Method java/io/PrintStream.println:(Z)V
   154:    new    #6//class java/lang/StringBuilder
   157:    dup
   
158:    invokespecial    #7//Method java/lang/StringBuilder."<init>":()V
   161:    ldc    #10//String beijing
   163:    invokevirtual    #8//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   166:    iload    4
   
168:    invokevirtual    #11//Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
   171:    invokevirtual    #9//Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   174:    astore    11
   
176:    getstatic    #16//Field java/lang/System.out:Ljava/io/PrintStream;
   179:    aload    10
   
181:    aload    11
   
183:    if_acmpne    190
   
186:    iconst_1
   
187:    goto    191
   
190:    iconst_0
   
191:    invokevirtual    #17//Method java/io/PrintStream.println:(Z)V
   194:    new    #6//class java/lang/StringBuilder
   197:    dup
   
198:    invokespecial    #7//Method java/lang/StringBuilder."<init>":()V
   201:    aload    9
   
203:    invokevirtual    #8//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   206:    ldc    #19//String  blogjava
   208:    invokevirtual    #8//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   211:    invokevirtual    #9//Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   214:    astore    9
   
216:    getstatic    #16//Field java/lang/System.out:Ljava/io/PrintStream;
   219:    aload    9
   
221:    ldc    #20//String helloworld blogjava
   223:    invokevirtual    #21//Method java/lang/String.intern:()Ljava/lang/String;
   226:    if_acmpne    233
   
229:    iconst_1
   
230:    goto    234
   
233:    iconst_0
   
234:    invokevirtual    #17//Method java/io/PrintStream.println:(Z)V
   237:    return

}




posted on 2008-01-09 00:08 菜园小鸟 阅读(1936) 评论(6)  编辑  收藏

FeedBack:
# re: 一题有关String笔试题的分析
2008-01-09 07:46 | vagrant
其实这也和另一个知识相关:= 和 equals区别.equals是判断两个对象的值是否相等,而=则判断值和地址是否相等.  回复  更多评论
  
# re: 一题有关String笔试题的分析
2008-01-09 08:24 | Matthew Chen
第一题不是说一种吗,好像看哪里说过常量池是编译期结束就创建好的,运行时不会创建。  回复  更多评论
  
# re: 一题有关String笔试题的分析
2008-01-09 09:29 | 隔叶黄莺
对于这种问题我基本是不愿多看细看的,讨论多了都无益,如果照很多人的想法可以无限伸展,就比如一个有许多个对象属性的类
Class1{
Object obj1;
Object obj1;
Object obj1;
Object obj1;
Object obj1;
.........
}

new Class1() 谁能说创建了几个对象,那如果属性嵌属性,很深很深层次的,又会创建几个对象,有多大意义呢

可能对于 new String("xyz") 就是存在一个常量池的问题,有时要考虑编译优化的问题,就这么简单,何必搞得这么复杂。  回复  更多评论
  
# re: 一题有关String笔试题的分析[未登录]
2008-01-09 10:34 | abc
这些原理是属于编程基础吧?  回复  更多评论
  
# re: 一题有关String笔试题的分析
2008-01-09 13:14 | 你是楼猪
讨论这没多大意义,很讨厌死抠这些的hr  回复  更多评论
  
# re: 一题有关String笔试题的分析
2008-01-09 20:10 | sitinspring
留个记号。  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航:
 

<2008年1月>
303112345
6789101112
13141516171819
20212223242526
272829303112
3456789

常用链接

留言簿(1)

随笔档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜