0

让我们看一下这段代码:

package rpg;

interface A {
    // An empty interface
}

public class WarriorClass extends CharacterClass implements A {

    final int bab;
    public WarriorClass(int a) {
        bab = a;
    }

    public static void main(String[] args) {
        A a = new WarriorClass(1);
        System.out.println(((WarriorClass) a).bab);
    }
}

第一个问题:为什么可以使用接口A作为类型a?第二个问题:既然 A 不知道 iVarbab为什么不知道

System.out.println(((WarriorClass) a).bab);

打印正确的值1

4

3 回答 3

3

您不会将类存储在接口“中”。您正在将对该类的引用存储在接口类的变量中。

Java 仅适用于引用。都具有相同的长度(如 C 中的指针)。引用是类型化的,因​​此您必须为其分配一个适当类的对象。

至于关系,扩展一个类或实现一个接口意味着新的类对象也属于原来的类。所以所有对象都是Object. 由于通过扩展/实现您确认新类遵循超类/接口的合同(规范),它们确实属于它。

于 2012-09-01T10:16:37.577 回答
1

你想在解释中走多低?

停留在类比的层面上,A a意味着“这是一个我可以插入任何 a/implements A 的地方。有一种方法可以让它适应。

由于您创建的对象实现了该接口,因此它将起作用。

在这一点上,任何可以用 any 完成的事情A都可以安全地完成a(安全因为它不会使整个事情崩溃,如果 ega为空,它仍然可以抛出异常,但你不能欺骗编译器生成调用没有该A方法的对象上的方法的代码)。

稍后您再次使用((WarriorClass)a). 这将检查发生在 中的任何内容a。如果为空,则结果为空。如果它是一个确实是 a 的对象WarriorClass,那么结果就是该对象,按原样访问。如果它是 的另一个实现A,则会出现异常。

在较低的级别,在这两种情况下都有一个引用存储在a. 编译器将确保您不会做绝对不可能的事情(A a = "abcde";例如),并且引用实际上只是一个数字(毕竟一切都在计算机中),它可以访问该对象。

当您调用任何A方法时,该数字将与任何参数一起传递给该方法(它是该方法的this来源)。

当您进行强制转换时,对象会按上述方式进行检查。结果是另一个允许访问对象的数字(可能是同一个),但这次程序知道该数字指的是 a WarriorClass(或 null)。因此,代码可以调用.bab它。它不会导致不可能的情况:如果它为 null,则正常检查会发现,如果a不是真的是 a WarriorClass,那么当你尝试施法时就会抛出。在这一点上,程序 100% 确定地知道它不可能是另一个类也实现了A.

于 2012-09-01T10:28:27.803 回答
0

回答第一个问题:变量可以声明为一个类型,并实例化为声明变量的子类型。

回答第二个问题:您正在进行强制转换,这意味着您明确地说变量 a 是您进行强制转换的类型,因此您可以使用/调用可以在您所在的上下文中访问的任何变量或方法.

于 2012-09-01T10:16:35.403 回答