【问题标题】:How to use casting with interface?如何在接口中使用强制转换?
【发布时间】:2015-08-27 13:41:04
【问题描述】:

为什么会出现以下输出/错误?

public class A1 {
    public void bar() {
        System.out.println("A1 bar");
    }

    public static void main(String[] args) {
        List<A1> list = new ArrayList<>();
        list.add(new B());
        /* add the missing lines here*/
    }
}

public interface A2 {
      void foo(List<A1> list, int idx);
} 

public class B extends A1 implements A2 {
    public void foo(List<A1> list, int idx) {
        A1 a1 = list.get(idx);
        if (a1 instanceof B) {
            System.out.println("It's a B!");
        } else {
            a1.bar();
        }
    }

    public void bar() {
        System.out.println("B bar");
    }
}

1) 将以下几行添加到 main 时:

list.add(new A1());
A2 a=(A2) list.get(0);
a.foo.(list,1);

既然动态类型不能是接口,为什么没有编译错误? (输出为“A1 bar”)。

2) 为什么以下几行会导致“运行时错误”而不是“编译错误”?

list.add(new A1());
A2 a = (A2) list.get(1);
a.foo(list, 0);

3) 对于以下类层次结构是否正确:

Interface Animal {...}
class Dog implements Animals {...}
class Poodle extends Dog {...}
class Labrador extends Dog {...}

以下行无法编译,因为动态类型是接口?

Animal animal=(Animal) poodle;

【问题讨论】:

  • 基本上你在继承自A2B:foo()方法中缺少@Override注释
  • 尽可能避免使用instanceof 。使用polymorphism 代替它。

标签: java interface casting


【解决方案1】:

为什么没有编译错误,因为动态类型不能 界面? (输出为“A1 bar”)。

某些东西可以同时是 A1 和 A2,例如 B。那么为什么编译器会因为它不在那种(运行时)情况下而显示错误呢? list.get(0); 将返回 A1,是的,但编译器没有机会知道它是否也是 A2。

2) 为什么以下几行会导致“运行时错误”而不是 “编译错误”?

两种可能性,取决于您添加它的位置。要么你得到一个 IndexOutOfBoundsException,因为编译器不计算列表的大小。为什么要呢?编译器应该做的事情是有限制的。在这种情况下,可能可以在编译时计算列表大小 - 但在许多其他情况下,它不是,因此编译器的工作不是检查这样的东西。

或者你得到一个 ClassCastException,因为你得到一个 A1 对象并尝试将它转换为 A2。这可以工作,例如,如果您的 A1 对象也是 B。但在您的情况下,它不仅仅是一个简单的普通 A1 对象,它也不是 A2。因此你不能把它合二为一。例如,一只狗可能是一只母狗,但它不是必须的。如果你尝试将非FemaleDog 强制转换为FemaleDog,那么你会得到一个异常。

Animal animal=(Animal) poodle;

...工作得很好,因为贵宾犬是狗,狗是动物,所以贵宾犬也是动物。

【讨论】:

  • 非常感谢!!你能解释一下为什么第二个问题会出现“运行时错误”吗?
  • 好的,这取决于你把它放在哪里。您的列表的大小只有 1,然后 get(1) 会抛出异常。或者,如果不是这种情况,那么您获取 A1 对象并尝试将其转换为 A2。但在这种情况下,您的 A1 对象也不是 A2(因为它不是 B),因此这是一个错误。
  • list.get(0) 属于“B”类型,那么为什么将其转换为“A2”是合法的——它可能会“切断”其扩展的可能性?
  • 在您的示例代码中,您可以有两种类型的对象:A1 对象和 B 对象。每个 B 对象也是 A1 对象和附加的 A2 对象。 A1 对象就是这样,A1。因此,如果您有一个 A1 列表,则不能确定其中的每个对象也都有一个 A2,因为这仅适用于 B 对象,而不适用于“纯”A1 对象。
猜你喜欢
  • 2013-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-05
  • 2011-07-23
  • 1970-01-01
  • 2014-01-16
  • 1970-01-01
相关资源
最近更新 更多