为什么在这种情况下演员是必要的?

时间:2015-08-31 21:38:47

标签: java

class MyClass {

   private String str;
   public MyClass(String str){
      this.str = str;
   }
   public int compare(Object o) {
      return str.compareTo(((MyClass)o).str); //line No.8
   }
}

class Client {
   public static void main(String[] args) {
      MyClass m = new MyClass("abc");
      MyClass n = new MyClass("bcd");
      System.out.println(m.compare(n));
   }
}

为什么在这段代码中,第8行中的强制转换(MyClass)o是必要的,尽管客户端使用带有MyClass类实例的参数调用compare方法?

当我将MyClass类中的compare方法修改为如下所示:

   public int compare(Object o) {
      System.out.println(o.getClass());
      System.out.println(((MyClass)o).getClass());
      return str.compareTo(((MyClass)o).str);
   }

然后,客户端将产生以下结果:

class MyClass
class MyClass

因此我不明白为什么上面的演员表是必需的以及为什么我不能这样做(没有演员到MyClass):

   public int compare(Object o) {
      return str.compareTo(o.str); 
   }

因为当我这样做时,我得到编译时错误:

str cannot be resolved or is not a field

2 个答案:

答案 0 :(得分:8)

这归结为编译器在编译时所知道的内容。在编译时,它知道将要传递给此方法的是Object类型。这意味着它可以保证与类Object关联的方法,但不能保证类型MyClass的方法。

因为compare方法接受类型Object或子类的任何参数,所以你可以传入任何内容。如果我像这样创建一个类MyOtherClass怎么办...

public class MyOtherClass {
    public String notStr;
}

我做的事情......

MyOtherClass myOtherClass = new MyOtherClass();
MyClass myClass = new MyClass();

myClass.compare(myOtherClass);

如果没有强制转换,您现在遇到的情况是,在运行时,它会尝试访问不存在的字段。使用强制转换来保证对象的类型正确,或者在尝试访问该字段之前它将失败。

就像一个旁白

我一直在使用一种名为Groovy的语言进行广泛的工作。它是一种基本上位于Java之上的语言,但它支持动态绑定和松散类型之类的东西(这就是你在这里所说的)。如果您必须拥有此类功能,那么我建议您查看documentation

答案 1 :(得分:1)

o compare中的Object类型为MyClass。这意味着它可以是Object实例的参数,但它也不能。 str没有任何名为MyClass的字段(因为它属于MyClass),因此无法从中获取该字段,因此代码无法编译。但是,如果转换为{{1}},它将有一个名为str的字段,因此它可以访问它。