当前位置:首页 > java练习题(含答案)
是在编译期就被确定了,所以“s1 == s2”;“abc”和“def”都是字符串常量,当一个字符串由多个字符串常量连接而成时,它自己也肯定是字符串常量(它在编译期就被解析为一个字符串对象了,即class文件中就已经存在“abcdef”),所以在字符串生成字符串对象时,s3也是String Pool中“abcdef”的一个引用。故JVM对于字符串常量的\号连接,在程序编译期,JVM就将常量字符串的\连接优化为连接后的值。
例程2: Java代码 1. String s1 = \ 2. String s2 = \ 3. String s3 = \ 4. String s4 = \ 5. String s5 = s1 + \ 6. String s6 = \ 7. String s7 = s1 + s2;
8. System.out.println(s3 == s4); 9. System.out.println(s3 == s5); 10.System.out.println(s3 == s6); 11.System.out.println(s3 == s7);
运行结果如下: true false false false
结果说明:JVM对于有字符串引用存在的字符串\连接中,而引用的值在程序编译期是无法确定的,即s1 + “def”无法被编译器优化,只有在程序运行期来动态分配并将连接后的新地址赋给s5。
例程3: Java代码 1. final String s1 = \ 2. String s2 = \ 3. String s3 = \ 4. String s4 = \ 5. String s5 = s1 + \ 6. String s6 = \ 7. String s7 = s1 + s2;
8. System.out.println(s3 == s4); 9. System.out.println(s3 == s5); 10.System.out.println(s3 == s6);
11.System.out.println(s3 == s7);
运行结果如下: true true false false
例程4: Java代码
1. final String s1 = \ 2. final String s2 = \ 3. String s3 = \ 4. String s4 = \ 5. String s5 = s1 + \ 6. String s6 = \ 7. String s7 = s1 + s2;
8. System.out.println(s3 == s4); 9. System.out.println(s3 == s5); 10.System.out.println(s3 == s6); 11.System.out.println(s3 == s7);
运行结果如下: true true true true
结果说明:例程3和例程4与例程2的区别是,例程3在字符串s1前加了final修饰,例程4在字符串s1和s2前都加了final修饰。对于final修饰的变量,它在编译时被解析为常量值的一个本地拷贝存储到自己的常量池中或嵌入到它的字节码流中。所以此时的s1 + “def”和\效果是一样的。接着后面两个含引用的字符串连接,JVM会进行相同的处理。故上面程序后面三个的结果为true。
例程5: Java代码 1. public 2. 3. 4. 5.
static void main(String args[]){ String s1 = \
final String s2 = getDef(); String s3 = \ String s4 = \
6. String s5 = s1 + s2;
7. System.out.println(s3 == s4); 8. System.out.println(s3 == s5); 9. }
Java代码
1. private static String getDef(){ 2. return \ 3. }
程序运行结果如下: false false
结果说明:JVM对于方法调用给字符串引用赋值的情况,引用指向字符串的值在编译期是无法确定的,只有在程序运行调用方法后,将方法的返回值“def”和“abc”动态连接并分配新地址赋值给s4,所以上述程序的结果都为false。
通过以上的例子可知: Java代码 1. String s = \+ \+ \
等价于: Java代码
1. String s = \
编译期,直接优化,进行常量连接。
对于:
Java代码 1. String 2. String 3. String 4. String
a b c s
= = = =
\ \ \ a + b
+ c;
就不等价于:等价于: Java代码
1. String s = \
最终结果等于: Java代码
1. StringBuilder builder = new StringBuilder (); 2. builder.append(a); 3. builder.append(b); 4. builder.append(c);
5. String s = builder.toString();
去看StringBuilder的toString()方法: Java代码
1. public String toString() {
2. // Create a copy, don't share the array 3. return new String(value, 0, count); 4. }
可以发现是通过new String(..)返回了一个String对象,也就是说在堆中创建了对象。这时候会不会在池中出现\这个对象呢?(question还没解决)
生成String s的过程中,编译器使用sb执行的过程:创建一个StringBuffer对象,使用append()向此StringBuffer对象直接添加新的字符串(而不是每次制作一个新的副本)。
对于String c = \,编译器将会先将\作为编译时常量,优化生成成字面常量\,然后生成一个StringBuilder对象,接着调用两次 append()方法,即:
String s = new Builder().append(\
对于String a = \,编译器分析a为引用变量,后面的\就不会作为编译时常量来运算了。相当于执行:
String s = new Builder().append(a).append(\.append(\.toString();
对于String b = \,这种形式的就没办法优化了,直接生成StringBuilder对象,然后调用三次 append()方法,即:
String s = new Builder().append(\.append(\.toString();
接着,我们再看以下代码: Java代码
共分享92篇相关文档