2012-04-05 43 views
4

昨日(2012年4月5日)我'尝试比较字符串,它是在环境:为什么在比较字符串,java 1.6.0_29,osx时可以使用“==”?

计算机1

  1. 的Java(TM)SE运行时环境(建立1.6.0_29-b11-402-11D50b)
  2. OS X 10.7.3

计算机2

  1. 的Java(TM)SE欠幅IME环境(建立1.6.0_29-b11-402-11D50b)
  2. 窗口7

计算机3

  1. 的Java(TM)SE运行时环境(建立1.6.0_29-b11-402- 11D50b)
  2. Linux操作系统Ubuntu 11.10

这是代码我'尝试

public class TComp{ 
    public static void main(String[] args){ 
     String a = "arif"; 
     String b = "arif"; 
     if(a==b){ 
      System.out.println("match!"); 
     } 
    } 
} 

据我所知,为了比较java中的字符串,我们应该使用.equal()函数,'=='将在这种情况下实施实习。但是,对于那些具有不同操作系统的所有计算机,为什么实习生在计算机1中工作正常,而在计算机2和计算机3中出现错误?

如果有任何一种词我错了,请更正。谢谢。

+5

简答:你有(非)幸运。 – Mysticial 2012-04-05 00:02:18

+1

可能的重复[在JDK 1.6中,可以将String equals操作替换为==吗?](http://stackoverflow.com/questions/5839196/in-jdk-1-6-can-string-equals-operation-可以被替换) – 2012-04-05 00:03:55

+0

较短的回答:使用'.equal' – 2012-04-05 00:04:29

回答

5

在同一个类中,编译器(在编译时)将所有字符串常量合并到.class文件常量池中。这意味着编译器将只存储一个字符串的副本(因为谁需要两个相同的常量在池中?)。

这意味着在一个班级内==比较字符串经常工作;然而,在你太激动之前,有一个很好的理由你不应该使用字符串的比较。 没有保证你比较的两个字符串都来自课堂常量池。

所以,

"foo" == new String("foo") 

是完全有可能失败,而

"foo" == "foo" 

可能会奏效。这威力很大程度上取决于执行的,如果你的代码来执行,而不是规范,你会发现自己在一个非常讨厌的惊喜,如果实现的改变是因为规范实际上并不需要实施。

总之,使用.equals(...)Object比较,每一次。为原始比较保留==和仅“比较相同的对象实例”。即使您认为两个Strings可能会被实施(或同一个对象),因为您永远不知道何时将运行在不同的类加载器上,不同的JVM实现中,或者只是决定不实施一切的机器上运行。

+0

根据JLS 3.10.5,''foo“==”foo“'应该总是返回true - 按Java规范而不是实现细节。同时,'“foo”== new String(“foo”)'应该总是为false(尽管'“foo”= new String(“foo”).intern()'应该为true)。如果一个JVM没有这样做,我会说这是一个错误。 – yshavit 2012-04-05 05:02:11

+0

@yshavit我不认为你错了,或者“foo”==“foo”不应该返回true;然而,“foo”==“foo”几乎总是错误的比较。如果你比较内容相等的对象(和字符串_对象),那么你应该使用'.equals(Object)',因为这是内容相等运算符。如果你决定不这样做,你最好在实例平等的基础上构建你的代码。直到您将它视为内容平等之前,优先考虑实例平等并不是一件坏事。不一致地优先选择实例相等性是过早优化的标志。 – 2012-04-05 14:58:59

+0

这里没有参数,尤其是因为在String中的第一次检查(并且实际上在大多数类中)是'if(this == other)return true;'。 – yshavit 2012-04-05 15:39:49

1

在一台计算机上,他们是同一个对象,而另一台却不是。该语言的规则并不指定它们是否是同一个对象,所以它可以以任何方式发生。

1

字符串实际上完全取决于编译器。 ==不“实习”任何东西;它只是比较对象的身份。在某些情况下,a和b可以指向同一个对象。在其他情况下,他们没有。两者都是合法的,所以你应该确实使用.equals()。请参阅http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.5

+0

你引用的链接驳斥了你的声明,即实际上是由编译器决定的。 '而且,一个字符串文字总是引用类String的同一个实例。这是因为字符串文字 - 或者更一般地说,是常量表达式(§15.28)的值的字符串 - 被“interned”,以便使用方法String.intern.' – yshavit 2012-04-05 04:58:43

0

使用==来比较对象根本不可靠。除非您真的在寻找完全相同的实例,否则绝对不应该使用==比较对象的相等性。

+0

@TravisJ共享唯一的实例。 – 2012-04-05 00:12:24

+0

@TravisJ Java没有这样的东西 – 2012-04-05 00:14:59

+0

@ Eng.Fouad - 不要猜测。 – 2012-04-05 00:20:48

0

==运算符确定两个对象引用是否指向同一个实例。

另一方面,.equals()方法比较对象内的实际字符。

这些应该与您所在的计算机无关。

+0

我觉得很有意思的是,愿意让你失望的人没有足够的能力去理解Java的==和equals语义。 – James 2012-04-05 00:24:30

+0

谢谢詹姆斯......我也是。 – Sam 2012-04-05 18:08:38

0

最好的事情总是使用.equals来比较对象。 但如果你需要使用==运算符的一些奇怪的原因,你需要确保比较.intern method的结果。 它始终返回interned值,doc告诉它它是唯一的。该文件说,所有的consts也是interned和独特的。

1

这是因为每当创建编译时常量字符串时,Java都会执行String interning

JLS 15.28。常量表达式

类型为String的编译时常量表达式始终是“interned”的,以便使用方法String.intern共享唯一实例。

这就是为什么你会得到一个真正的当用“==”来比较,因为他们实际上是同一个对象,将String.valueOf()的工作方式相同的字符串常量。

String x = "a"; 
String y = "a"; 
System.out.println(x == y); // true 


String w = new String("b"); 
String z = "b"; 
System.out.println(w == z); // false 
+0

谢谢,检查的方法是有帮助的。 :) – 2012-04-05 01:25:14

相关问题