当前位置: 首页 > 面试题库 >

在此示例中,为什么即使在调用getClass()之后,也仍然必须对对象进行类型转换以确保其类型?

郭修平
2023-03-14
问题内容

我正在使用Java上的OOP上的MOOC,它提供了一个我不完全理解的示例。在该示例中,Book已创建一个类,并且他们正在为Book该类构造“等于”重写方法。新equals()方法采用任何对象的参数。如果该参数是Book与该对象具有相同名称和PublishingYear
的对象,则返回true
Book。因为参数对象可以是Object类的任何对象,所以在调用getPublishingYear()getName()方法之前,如果在不在Book类中的对象上调用该对象,则会抛出错误,因此该equals()方法将检查以确保确实Book通过此代码处理对象

 if (getClass() != object.getClass()) {
        return false;
 }

我非常了解(我认为)。我不明白的是,为什么在上面的代码之后,他们随后将参数对象转换为a
Book,然后在新转换的对象而不是原始对象上调用getPublishingYear()getName()

Book compared = (Book) object;

if (this.publishingYear != compared.getPublishingYear()) {
    return false;
}

if (this.name == null || !this.name.equals(compared.getName())) {
    return false;
}

    return true;

我不明白为什么如果由于上述getClass()检查该对象不是Book类型的方法应该已经返回false,则为什么必须执行此步骤。我尝试在没有此额外转换步骤的情况下进行编译,发现该步骤确实是必需的-
如果不包括此步骤getPublishingYear()getName()则编译器将显示“找不到符号”错误。那我想念什么呢?

equals()完整的方法:

@Override
public boolean equals(Object object) {
    if (object == null) {
        return false;
    }
    System.out.println(getClass());
    if (getClass() != object.getClass()) {
        return false;
    }

    Book compared = (Book) object;

    if (this.publishingYear != compared.getPublishingYear()) {
        return false;
    }

    if (this.name == null || !this.name.equals(compared.getName())) {
        return false;
    }

    return true;
}

问题答案:

将变量强制转换为数据类型基本上是告诉编译器“相信我,我知道我在做什么”。在将“对象”强制转换为“书”的情况下,您要确保编译器该对象实际上是一本书,并相应地进行操作。这也迫使您相信自己知道自己在做什么。

编辑:我不确定是否要问为什么需要实际的转换(添加“(Book)”)或为什么需要对Book变量进行赋值。我回答了前者。如果问题是后者,则答案是您需要Book变量,以便可以使用Book方法。

由于您拥有进行确定的工具,因此您会认为不需要进行强制转换,因为编译器能够生成用于确定的相同代码,只需执行赋值即可:

Book book = object;           // Wrong

代替

Book book = (Book) object;    // Right

如果希望编译器“仅知道”该对象是Book,则每次使用Book方法时,编译器都必须测试Object。通过在分配中明确告诉它,编译器可以创建特定于Book类的代码,而无需进一步检查Object。



 类似资料:
  • 问题内容: 尽管Java中的所有类都是Object类的子类,但是与其他对象类型不同,但是如果没有强制类型转换,则不能将Object类型的引用变量分配给任何其他引用类型。 例如: 问题答案: 您想知道为什么我们使用显式类型转换。这就是关于继承的一切- 让我来清除此-让我们有两个类 A类 和 B类 。和 B类 是子类的 类A 。这意味着 Class B 具有 Class A的 所有功能,这意味着 Cl

  • 我试图抛出一个目标。但是在运行时,对象类仍然是一个派生类。 那么为什么类属性没有改变呢?

  • 我以前做过这件事,但忘记了,无法在网上轻易找到答案。 我应该用什么类型填写?

  • 问题内容: 我有以下代码: 注释行无法编译。 为什么即使协议要求,我也必须强制将协议类型对象强制转换为符合该对象类型的对象? 问题答案: 采用该协议告诉编译器此特定响应,至少不会更多。 在相反的结论,并 没有 成为必然。 如果受影响的类不是,约束只是编译器 在编译时 抱怨的另一信息。 在您的情况下,对编译器进行批注仅知道对作出响应。它不知道类型实际上是的子类。 因此,如果要访问具体类的属性,请不要

  • 问题内容: 从Java 5开始,我们已经对原始类型进行装箱/拆箱,因此将其包装为,依此类推。 我最近看到许多新的Java项目(肯定要求JRE的版本至少为5,如果不是6的话)正在使用int而不是,尽管使用后者要方便得多,因为它具有一些用于转换的辅助方法到long的值等。 为什么有些人仍然在Java中使用原始类型?有什么切实的好处吗? 问题答案: 在Joshua Bloch的有效Java条款 5:“避

  • 问题内容: 在下面的示例中(来自我的Coursepack),我们希望给该Square实例c1一些其他对象的引用p1,但前提是这两个对象是兼容类型的。 我在这里不明白的是,我们首先检查p1确实为Square,然后仍将其强制转换。如果是Square,为什么要投射? 我怀疑答案在于表观类型和实际类型之间的区别,但是我还是很困惑…… 编辑: 编译器将如何处理: Edit2: 是instanceof检查实际