我正在研究基本的java程序,我发现了与你分享的有趣的事情。 foo()给出输出(s == s1)= false,bar给出(s == s1)= true。
我想知道为什么会这样。
public class StringTest
{
public static void main(String[] args){
foo();
bar();
}
public static void foo(){
String s = "str4";
String s1 = "str" + s.length();
System.out.println("(s==s1) = " + (s1==s));
}
public static void bar(){
String s = "str4";
String s1 = "str" + "4";
System.out.println("(s==s1) = " + (s1==s));
}
}
答案 0 :(得分:16)
在后一种情况下,编译器会优化字符串连接。由于这可以在编译时完成,因此它们都引用相同的常量字符串对象。
在前一种情况下,length()
调用在编译期间无法优化。在运行时,会创建一个新的字符串对象,该字符串对象与字符串常量(但等于它)
答案 1 :(得分:3)
bar()
中的字符串连接可以在编译时完成,因为它是一个只由编译时常量组成的表达式。虽然字符串s
的长度在编译时显然是已知的,但编译器不知道length()
返回该已知值,因此它不会用作常量。
答案 2 :(得分:2)
当您编写如下代码行时:
String s1 = "str" + "4";
然后编译器足够聪明,可以将其优化为:
String s1 = "str4";
Java中的文字字符串在字符串池中管理。如果您有两个具有相同内容的文字字符串(例如第二个示例中的s
和s1
),则只会创建一个String
对象,这两个对象将由两个共享变量
Java中的==
运算符检查两个变量是否引用同一个对象。由于第二个示例中只有一个String
对象,s == s1
将为true
。
答案 3 :(得分:2)
String s1 = "str" + s.length();
String s1 = "str" + "4";
在第一种情况下,s.length()将返回类型 int 的值,在第二种情况下,类型为 String 即使两个案例中的数字都是4,但类型不一样:)
答案 4 :(得分:0)
这可能与foo()可能在s.length()(。toString())中创建一个新的String实例这一事实有关,其中bar()只是连接一个常量。我不知道它的细节,但我的直觉告诉我这个方向
答案 5 :(得分:0)
如果我需要猜测我会说java编译器对bar()执行一些优化。在编译时,很明显“str”+“4”可以替换为“str4”,因为Strings是不可变对象,它实际上与用于s初始化的“str4”-String完全相同。
在foo()中,优化不是直接向前发展。通常,不能很容易地预测值s1变量(实际上这个例子非常直接)。所以java编译器会为s和s1生成两个不同的变量。
“==”运算符不会比较字符串的值!它检查这些是否是相同的对象。要比较字符串的值,请使用“equals”方法,如下所示:
String s = "str4";
String s1 = "str" + s.length();
System.out.println("(s==s1) = " + (s1.equals(s2));
答案 6 :(得分:0)
您应该尝试使用String类的实习方法。 Java保存了类似于字典的内容,其中存储了所有不同的字当您创建可在编译时计算的字符串对象时,Java会在其字典中搜索它。如果它找到了字符串,它只存储对该字符串的引用(实际上是由intern方法返回的)。
你应该注意到:
"str4" == ("str" + "str4".length())
返回false,但是
"str4" == ("str" + "str4".length()).intern()
返回true,因为唯一的“包装器”是另一个对象。