为什么平等不使用铸造的等于方法?

时间:2013-10-21 02:12:41

标签: java

正如问题所说的那样。理想情况下,答案应该是错误的,因为它将使用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

这与多态性有关;我知道如何equals()和实习工作。

相关主题:铸造图形 - >的Graphics2D

前面提到的场景是向上转换的情况,其中String被下载到Object。

但是,对此的常见用法实际上是向下转换 GraphicsGraphics2D以使用图形本身不存在的升级或新方法。为什么我们可以向上倾斜,而不是垂头丧气。

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?
    }
}

5 个答案:

答案 0 :(得分:4)

您将cat投射到Object,但这不会改变catString 实例的事实。 Java执行dynamic binding(又称后期绑定),这意味着在运行时基于对象是实例的类来解析方法调用。在这种情况下,这仍然是String,这意味着将使用String#equals()不是 Object#equals()。您将cat2转换为Object这一事实几乎没有什么区别 - equals()无论如何都需要Object参数。

这是一种向自己证明这一点的简单方法:

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

同样的原则在这里起作用。 o类型为Object,但它是String个实例,因此String的{​​{1}}被调用。


考虑以下类结构:

getClass()

现在,当我们有像

这样的东西时
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");
    }
}

然后会调用A b = new B(); b.foo(); 的{​​{1}}方法。这是上述现象。你问的是:

B

我们在此处出现错误的原因是因为无法保证foo将采用A b = new B(); b.bar(); // error 方法。对于我们所知道的(或者更确切地说,编译器知道),b可以是具有谁知道什么的bar()实例。出于这个原因,我们必须执行显式转换:

b

这是因为Java是静态类型的(即使它执行动态绑定)。

答案 1 :(得分:2)

实例方法在运行时根据其动态类型进行解析。 这是多态/后期绑定。无论您将对象强制转换为静态类型Object,它的运行时类型仍为String,因此String#equals(Object)将是使用

  

为什么我们可以向上倾斜而不是向下倾斜。

给出两个班级

public class A {

}

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

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

答案 2 :(得分:1)

由于所有方法在java中都是默认的虚拟,所以即使您将其输入到Object,它也会调用String equals方法,因为该对象是类型String不是Object

这也称为后期绑定或运行时多态。

答案 3 :(得分:0)

这不是Java如何解决应该使用哪种方法的方法。即使你在运行时将它转换为Object,也会使用String的equals。并且String的equals不检查引用相等,但是如果字符串“逻辑”相等。

这是因为所谓的“动态链接”,您可以谷歌或尝试阅读它here.

答案 4 :(得分:-1)

String Object是不可变对象之一,其他对象如Integer。

所以这是一个简单的比较,你创建了2个Integer对象(相同的值)并执行相同的操作。返回2个整数是相等的更有意义。

从示例中,我猜你现在可能已经知道了不可变类的目标:它们旨在保留它们的状态并简化与它们相关的操作,就像一个int。