Java和动态类型

时间:2014-02-21 00:40:05

标签: java types casting

假设您有两个类:

public abstract class X {
  public abstract void insert(Object item);
}

public class Y extends X {
  protected Object a;
  public void insert(Object item) {
    a = item;
  }
}

当您尝试以下操作时:

X x = new Y();
x.insert(5);

一切都很好。但是,当你还添加

x.a;

你为什么要这样做:

((Y) x).a;

最后一行?

提前谢谢!

4 个答案:

答案 0 :(得分:4)

  

但是,编译器是否应该认识到x的动态类型实际上是Y?

不,编译器不会分析程序以确定变量的动态类型。在编译时,它仅适用于静态类型。

  

对于第二行似乎理解这一点,因为insert方法实际上最终给了x一个“a”的值。

方法解析在运行时完成,可以进行动态输入。这不是编译器执行分辨率,而是运行时。

答案 1 :(得分:0)

方法/字段分辨率基于引用变量的类型(在这种情况下为X)完成。 X上不存在'a',因此您必须转换为Y以告诉编译器将该引用视为Y引用,因此可以解析'a'。

答案 2 :(得分:0)

动态绑定在这里无关紧要。静态绑定是重要的事情。

当您定义对象eas X时,您的对象具有X x = ...类型的静态绑定。编译器不知道该类型中的任何a

答案 3 :(得分:0)

假设你有这个代码:

public abstract class X {
  public abstract void insert(Object item);
}

public class Y extends X {
  protected Object a;
  public void insert(Object item) {
     a = item;
  }
}
public class Z extends X {
  public void insert(Object item) {
     /* nothing */
  }
}

// method signature : public X someSecretBlackBoxMethod()
X x = someSecretBlackBoxMethod();

现在,someSecretBlackBoxMethod方法返回扩展X的类的具体实例,对吧?那是哪一个,YZ

好吧,编译器也不知道。这就是编译器无法解析x.a的原因。但是,如果将其强制转换为Y(即((Y)x).a),则编译器知道 x 应该是{的实例{1}}因此,了解该属性。现在,在运行时,如果Y 不是 x的实例,那么您获得了ClassCastException