简体   繁体   English

为什么等于不使用强制转换的equals方法?

[英]Why is the equal not using the casted equals method?

Simply the just as the question have stated. 正如问题所表明的那样。 The answer should ideally be false, since it would be using the Object#equal which is simply reference comparison. 答案在理想情况下应该是错误的,因为它将使用Object#equal,它只是引用比较。

    String cat = new String("cat");
    String cat2 = new String("cat"); 

    System.out.println(((Object) cat).equals((Object) cat2)); // returns true, but should be false

This has to do with polymorphism; 这与多态有关。 I know how equals() and interning work. 我知道equals()和实习如何工作。

RELATED TOPICS: CASTING GRAPHICS -> GRAPHICS2D 相关主题:铸造图形-> GRAPHICS2D

The aforementioned scenario is a case of upcasting where String is being downcasted to Object. 前面提到的场景是向上转换的情况,其中将字符串向下转换为对象。

However, a common use of this is actually downcasting Graphics to Graphics2D to use upgraded or new method that don't exist in Graphics itself. 然而,这个普通的使用实际上是向下转换 GraphicsGraphics2D使用中不图形本身存在升级或新方法。 How come we can upcast and NOT downcast. 我们怎么能上投而不是下投。

import java.awt.*;
import javax.swing.*;

    public class Example extends JPanel {
        public static void main (String []args){
        JFrame frame = new JFrame();
    }
    public void paintComponent(Graphics g){
        Graphics2D g2 = (Graphics2D) g;             // How can we be sure the informal 
        g2.drawLine(0,0, getWidth(), getHeight());  // parameter contains those methods?
    }
}

You cast cat to Object , but that doesn't change the fact that cat is a String instance . 您将catObject ,但是不会改变catString 实例的事实。 Java performs dynamic binding (aka late binding), meaning that method invocations are resolved at runtime based on the class of which the object is an instance. Java执行动态绑定 (也称为后期绑定),这意味着将在运行时根据对象是实例的类来解析方法调用。 In this case, that's still String , which means String#equals() will be used, not Object#equals() . 在这种情况下,它仍然是String ,这意味着将使用String#equals()而不是 Object#equals() The fact that you cast cat2 to Object makes little difference -- equals() takes an Object argument anyway. cat2Object的事实差别不大cat2 equals() cat2采用Object参数。

Here's an easy way to prove this to yourself: 这是向自己证明这一点的简单方法:

String s = "abc";
Object o = (Object) s;  // we don't really need an explicit cast

System.out.println(s.getClass());
System.out.println(o.getClass());
class java.lang.String
class java.lang.String

The same principle is at work here. 同样的原则在这里起作用。 o is of type Object but it is a String instance, and so String 's getClass() is called. oObject类型的,但是它是String实例,因此调用StringgetClass()


Consider the following class structure: 考虑以下类结构:

class A {
    public void foo() {
        System.out.println("A foo");
    }
}

class B extends A {
    public void foo() {
        System.out.println("B foo");
    }

    public void bar() {
        System.out.println("B bar");
    }
}

Now, when we have something like 现在,当我们有类似

A b = new B();
b.foo();

then B 's foo method will be invoked. 然后将调用Bfoo方法。 This is the phenomena described above. 这是上述现象。 You're asking about something like: 您正在询问类似以下内容:

A b = new B();
b.bar();  // error

The reason we have an error here is because there is no guarantee that b will have a bar() method. 我们在这里出现错误的原因是因为不能保证b将具有bar()方法。 For all we know (or, rather, the compiler knows), b could be a C instance with who-knows-what. 就我们所知(或更确切地说,编译器知道), b可以是一个具有who-knows-what的C实例。 For this reason, we have to perform an explicit cast: 因此,我们必须执行显式强制转换:

A b = new B();
((B) b).bar();    

This follows from the fact that Java is statically typed (even though it performs dynamic binding). 这是由于Java是静态类型的(即使它执行动态绑定)。

Instance methods are resolved at run time based on their dynamic type. 实例方法根据其动态类型在运行时解析。 This is polymorphism/late binding. 这是多态性/后期绑定。 Regardless of you casting the object to a static type of Object , it's runtime type is still String , so String#equals(Object) will be used. 不管您将对象强制转换为静态类型的Object ,它的运行时类型仍然是String ,因此将使用String#equals(Object)

How come we can upcast and NOT downcast. 我们怎么能上投而不是下投。

Given two classes 给定两个班

public class A {

}

public class B extends A {
    public void doSomething() {}
}

and

A a = new B();
a.doSomething(); // this won't compile because A doesn't declare a doSomething() method
((B) a).doSomething(); // this is fine because you are now calling the method on the static type B
// you might get a ClassCastException here if the runtime type of a wasn't B

As all the methods are default virtual in java so even though you type casted it to Object it will call String equals method because the object is of type String not of Object . 由于所有方法都是Java中默认的虚拟方法,因此即使您将类型强制转换为Object它也会调用String equals方法,因为该对象的类型不是String而是Object

This is also called late binding or runtime polymorphism. 这也称为后期绑定或运行时多态。

That's not how Java resolves which method should be used. 这不是Java解析应使用哪种方法的方式。 Even though you are casting it to Object at runtime String's equals will be used. 即使在运行时将其强制转换为对象,也将使用String的equals。 And String's equals doesn't check reference equality but if the strings are "logically" equal. 而且String的equals不会检查引用的相等性,但是如果字符串在逻辑上相等。

This is due to so called "dynamic linking" you can google it or try reading about it here. 这是由于所谓的“动态链接”所致,您可以在Google上搜索它或尝试在此处进行阅读

String Object is one of the immutable objects, others like Integer. 字符串对象是不可变对象之一,其他则是整数。

So here is a simple comparison, you created 2 Integer objects(the same value) and do equal operation. 所以这是一个简单的比较,您创建了2个Integer对象(相同的值)并进行相等的操作。 It makes more sense returning the 2 Integers are equal. 返回两个整数相等更有意义。

And from the example, I guess you might now know the objective of immutable classes: they are designed to retain their state and simplify operations relate to them, just like an int. 从示例中,我想您可能现在已经知道了不可变类的目标:它们被设计为保留其状态并简化与它们相关的操作,就像int一样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM