【问题标题】:Difference between Equals/equals and == operator?等于/等于和 == 运算符之间的区别?
【发布时间】:2009-06-09 19:13:37
【问题描述】:

a == ba.Equals(b) 有什么区别?

【问题讨论】:

  • 一个检查它们是否表示相同的对象(等于),另一个检查它们是否相同的对象(= =)
  • Eric Lippert 对此有很好的blog post。他专门谈论 C#,但我想 java 的原因会相同或非常相似。
  • C# 版本为:stackoverflow.com/questions/772953/…。让我去尝试寻找Java版本...
  • 令人惊讶的是,Java版本之前似乎没有被问过,至少没有直接问过。我能找到的最接近的是stackoverflow.com/questions/513832/…
  • 可能是因为它已记录在案并且随时可用。

标签: c# java


【解决方案1】:

假设ab的类型是引用类型:

  • 在 Java 中,== 将始终比较 identity - 即两个值是否是对同一对象的引用。这也称为引用相等。 Java 没有任何用户定义的运算符重载。

  • 在 C# 中取决于。除非有一个重载的运算符来处理它,否则 == 将表现得像 Java(即比较引用相等)。但是,如果存在与ab编译时 类型匹配的重载(例如,如果它们都被声明为字符串),则将调用该重载。这可以表现出它想要的样子,但它通常实现值相等(即ab可以引用不同但相等的值,它仍然会返回true) .

在这两种语言中,a.Equals(b)a.equals(b) 将调用Object 声明的虚拟Equals/equals 方法,除非a 的编译时类型引入了更具体的重载.这可能会或可能不会在a 引用的对象的执行时类型中被覆盖。在 .NET 和 Java 中,Object 中的实现也会检查身份。请注意,这取决于重载解析所依赖的执行时类型,而不是编译时类型

当然,如果anull,那么当你尝试调用a.equals(b)a.Equals(b) 时,你会得到一个NullReferenceException/NullPointerException

【讨论】:

  • java中没有虚拟方法,其实没有'virtual'关键字,每个方法都是.net调用的虚拟方法(可以被子类覆盖)
  • 更准确地说,== 比较两个表达式的,不管表达式是原始类型还是指针。如果这些表达式是“Dog d”或“new Dog()”之类的指针,那么您要测试的是“表达式是否指向同一个对象”。 .equals() 方法旨在用于检查语义相等性;两个对象是否具有相同的“意义”。
  • @Pablo:尝试覆盖 Object.getClass()。
  • @Scott:问题是当你引入自动装箱等时事情变得更加棘手。如果 a 和 b 是相同的类型并且不涉及重载,我同意。跨度>
  • @Ashwin:您在答案一开始就错过了“假设ab 的类型是引用类型”,这在您的示例中并非如此。
【解决方案2】:

== 运算符会检查两个对象是否完全相同,这在大多数情况下是不可行的。 Equals 方法将能够在内部比较两个对象

例子:

class Mycar
{
  string color;
  Mycar(string str)
 {
   color = str;
 }
}   

Mycar a = new Mycar("blue");
Mycar b = new Mycar("blue");
a==b // Returns false
a.Equals(b) // Returns true

【讨论】:

  • 这是什么语言?在C#中,除非你自己写Equals方法,否则默认会使用引用相等(和==一样)
【解决方案3】:

这取决于ab的类型。

特别是,Equals 是一个虚方法,因此它的行为不依赖于 a 和 b 的编译时类型。

在 Java 中,== 将始终按引用进行比较,这不一定是您想要的,尤其是对于字符串。

在 C# 中,== 可以重载,但不是虚拟的(它是 static 方法)。因此,如果ab 被声明为object,它将通过引用进行比较,即使它们的实际类型重载operator ==

另外,如果 a 是 nulla.Equals(b) 将抛出 NullReferenceException(Java 中的 NullPointerException)。

【讨论】:

  • == 不能被覆盖 - 它可以被重载
【解决方案4】:
String a = "toto".Substring(0, 4);
String b = "toto";
Object aAsObj = a;
Assert.IsTrue(a.Equals(b));
Assert.IsTrue(a == b);
Assert.IsFalse(aAsObj == b);
Assert.IsTrue(aAsObj.Equals(b));

这个测试在.NET中通过,诀窍是Equals是一个方法,而==是一个static方法,所以aAsObj == b使用

static bool Object.operator==(object a, object b) //Reference comparison

a == b 使用

static bool String.operator==(string a, string b) //String comparison

a.Equals(b)aAsObj.Equals(b) 总是使用:

bool String.Equals(Object obj) //String comparison

【讨论】:

    【解决方案5】:

    == 是语言中的基本运算符。运算符 == 测试两个对象引用变量是否引用了完全相同的对象实例。

    equals () 是一个实例方法,它基本上由 java.lang.Object 类定义。方法 .equals() 测试要比较的两个对象是否相等,但它们不必是同一对象的完全相同的实例。

    == 运算符始终为您提供相同的结果,但 equals () 方法根据您的实现(实现的逻辑)为您提供输出。正确覆盖 equals:覆盖 equals () 方法时的注意事项。

    1.自反:对于任何非空引用 x,x.equals(x) 应该返回 true。

    2。对称:对于任何非空引用 x 和 y,如果 x.equals(y) 为 true,则 y.equals(x) 必须返回 true。

    3.传递:对于任何非空引用 x 、 y 和 z,如果 x.equals(y) 为真,y.equals(z) 为真,则 x.equals(z) 必须返回真。

    4.一致:对于任何非空引用 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回 false,而不会更改为 equals 比较提供的信息。

    5.对于任何非空引用 x,x.equals (null) 必须返回 false。 注意:如果 o1.equals (o2) 为真,则 o1.hashcode () ==o2.hashcode (),但反过来可能是也可能不是。

    示例:

    整数 i = 新整数 (10); 整数 j = i;

    在上面的代码中。 i == j 为真,因为 i 和 j 都指向同一个对象。

    整数 i = 新整数 (10); 整数 j = 新整数(10);

    在上面的代码中,i == j 是 FALSE,因为尽管它们的值都是 10,但它们是两个不同的对象。但 i.equals (j) 将返回 true。

    使用自动装箱

    整数 i = 10;
    整数 j = 10;
    布尔 b = (i == j);
    System.out.println(b);

    这将返回 TRUE,因为介于 -127 到 128 之间的整数会被池化,因此在这种情况下,它们都是相同的对象(JVM 不会创建新对象,而是会从池中检索它)。

    String 类覆盖了 equals 方法,所以这里有一个 equals 与 == 的例子 字符串 s1 = 新字符串 ("abc"); String s2 = new String("abc");

    注意:字符串是在字符串常量池中创建的,所以当我们创建类似 String s=”abc” 时,它将通过调用本地方法 intern () 检查池,如果它确实存在于现有池中没有找到任何字符串,那么它会创建一个新的,但是如果我们调用 new 操作符,那么它会创建一个新的字符串,而不管检查池是否存在。

      public class StringEqualityTest {
        public static void main(String []a){
    
        String s1=new String("abc");
        String s2=new String("abc");
    
         System.out.print("s1.equals(s2)  :"+s1.equals(s2)+"  s1==s2   :");
         System.out.println(s1==s2);
    
         String s3="abc";
         String s4="abc";
    
         System.out.print("s3.equals(s4)  :"+s1.equals(s2)+"  s3==s4   :");
         System.out.println(s3==s4);
    
           }
    
           }
    

    输出: s1.equals(s2):真 s1==s2:假 s3.equals(s4) :true s3==s4 :true

    【讨论】:

      【解决方案6】:

      a == b 如果引用包含相同的值,即它们指向同一个对象,或者它们都为空,则返回 true。

      equals() 方法可以被覆盖来比较对象。例如,在Strings 上,如果字符串包含相同的字符串,即使它们是不同的字符串对象,该方法也会返回true。您可以对自己的对象做类似的事情。

      如果 o 为空引用,o.equals() 将抛出异常。

      【讨论】:

        【解决方案7】:

        == 使用对象的引用,或者如果是整数/浮点数等,那么它会比较实际数字。从技术上讲,它只是比较内存位置中的内容。 而.equals 使用对象类中的一个方法来比较对象,它可以被您的各个类覆盖。 此外,由于数组也处理引用,因此不使用array1[i] = array2[i]、使用arraycopyclone() 也很有帮助。 我觉得.equals也可以和数组一起使用

        【讨论】:

          【解决方案8】:

          假设我们有ab 或两个不同的对象,我们想比较这两个对象引用。然后我们使用== 运算符,当使用a.equals(b) 时,它会比较字符串值。

          【讨论】:

          • AFAIK == 和 Equals() 会做同样的事情。只有在使用 ReferenceEquals-Function 时才会比较对象引用。另外,如果anulla.Equals(b) 将抛出一个NullReferenceException
          【解决方案9】:

          == 检查对象引用,基本上它比较哈希码。 Equals 使用对象中的内容。请记住,我们必须在我们的类中相应地覆盖.equals 方法。

          【讨论】:

            【解决方案10】:

            == 检查引用是否指向内存中的同一个对象

            现在,

            虽然对象类中equals方法的代码只不过是检查==的引用,但是可以重写它来添加你自己的相等检查。

            在像 String 这样的类中,被覆盖的方法会检查字符串文字是否正确。所以基本上它可以用来检查值是否相同。

            【讨论】:

              【解决方案11】:

              ==,它只根据它们的地址返回一个哈希码的值,因此即使字符串或任何类似的数据也返回不同的地址,它也返回 false....这是对条件的帮助,返回布尔值价值。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2011-05-16
                • 2014-06-08
                • 1970-01-01
                • 2021-09-01
                • 2018-07-04
                • 2012-11-28
                • 2019-02-11
                • 2015-04-13
                相关资源
                最近更新 更多