正如问题所说的那样。理想情况下,答案应该是错误的,因为它将使用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。
但是,对此的常见用法实际上是向下转换 Graphics
到Graphics2D
以使用图形本身不存在的升级或新方法。为什么我们可以向上倾斜,而不是垂头丧气。
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?
}
}
答案 0 :(得分:4)
您将cat
投射到Object
,但这不会改变cat
是String
实例的事实。 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。