一题有关String笔试题的分析
题目: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类型的特殊性,编译器会在编译时做一些特殊处理,所以情况会变得稍微复杂一点。
1
public
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
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
}
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
}