Java类型系统:这些分配,方法调用和类型强制转换为什么会失败?

时间:2018-11-12 11:45:48

标签: java types casting variable-assignment

假设我定义了以下接口和类:

public interface I { void a(); }

public class A implements I {
    public void a() { System.out.println("A"); }
}

public class B implements I {
    public void a() { System.out.println("B"); }
    public void b() { System.out.println("C"); }
}

然后运行以下代码:

public class Main {
    public static void main(String[] args) {
        A a = new A();
        B b = new B();
        I i;
        i = a;
        i.a();    // prints "A"
        i = b;
        i.a();    // prints "B"
        i.b();    // 1st problem: i can't seem to find method b. Why?
        b = i;    // 2nd problem: b can't be assigned to i although i references an object of class B?
        b = (B)i; //              why does this work fine...
        a = (A)i; // 3rd problem: ...but this here doesn't?
    }
}

这是我的问题:

第一个问题

为什么不能i.b()被叫?

i指向与b相同的对象,B类的对象确实具有方法b

那么,为什么i.a()调用正确的方法(打印出“ B”的方法)却i.b()却根本无法解析?

i被声明为I类型(接口)的事实与此有关吗?这是否意味着在分配X x = new Y()中,Y extends X中,一个人只能在x中声明的X上调用方法,而不仅限于{{1 }}?

第二个问题

尽管Y引用了类b的对象,为什么不能将i分配给iBb已经引用了同一对象,不是吗?因此,如果我尝试将i分配给b,为什么会导致错误-最终结果应该与该赋值之前的程序 的状态相同,除非我缺少重要的东西。

第三个问题

为什么我现在不能将i转换为i,但我为什么不能将B分配给b,为什么不转换ii工作吗?

我假设我的困惑源于参考变量和它们所引用的对象之间不清楚的区分,以及这些变量和对象的类型之间的差异。我只是无法完全解释这些情况-特别是第一个问题使我非常困惑。

3 个答案:

答案 0 :(得分:0)

第一个问题:  您可以使用接口引用仅调用其声明的方法

对于第二个问题:  您可以使用接口引用来调用实现该接口的类中的方法。但是,由于接口引用没有任何可调用的方法,因此无法将接口引用分配给类引用。

第三个问题: 您先前已分配

        i=b 

因此

     b=(B)i 

工作正常。

但是,           a =(A)i 无法使用,因为我存储b而不是a

答案 1 :(得分:0)

首先,学习 Java (和/或 OO(面向对象))编程...

  1. 变量i是对实现接口I的对象实例的引用。接口b()中未声明方法I,因此无法通过i.b()看到方法。
    为了能够调用它,i需要强制转换,例如:((B) i).b()
  2. 变量b是对对象的引用,该对象是类B的实例,不能分配给本身未声明为B实例的任何引用。 br /> 同样,需要强制转换,例如:b = (B) i
  3. B不是类A的子级。它们都实现了接口I,但是A不是B的父级。

答案 2 :(得分:0)

这根本不是问题,而是继承和政治化的行为。

请注意,当您

I i = new A();

左手边(I)告诉编译器可以使用该引用调用哪些方法。

右侧(A)会告诉Runtime使用该方法调用应执行哪个方法

所以就您而言

1个问题

您不能呼叫b(),因为b()不在界面I

2问题

您正在将接口转换为对象b,然后调用b(),以便其正常工作。