当基类的引用变量指向JAVA中的子类对象时,内部会发生什么

时间:2014-08-26 08:55:29

标签: java class object inheritance reference

ABC a1 = new XYZ(); XYZ扩展ABC的地方。

数据类型告诉我们变量将包含什么 让我感到困惑的是,如何让一个引用变量指出它不是变量?

即使我们能做到这一点,有什么好处呢?

内部如何运作。我们写的时候 ABC a1 = new XYZ();

2 个答案:

答案 0 :(得分:2)

这种模式为您提供了灵活性。

排序算法示例:

private List<Integer> myCollectionToSort = new ArrayList<>();

ArrayList延伸List(从语义上讲,ArrayListList,因此 IS List ),这一行是有效的。

对于您的算法,您可能不需要知道myCollectionToSort是一个ArrayList。您的算法将仅使用List接口的方法。

稍后,您会发现ArrayList进行了大量无用的操作,而您又不想再使用它了。由于您从未使用ArrayList的特定方法,而只使用List接口中的方法,因此您唯一需要更改的是List实现:

//LinkedList is more adapted for "writing" operations.
private List<Integer> myCollectionToSort = new LinkedList<>();

答案 1 :(得分:0)

想想这样:

鉴于这两个类:

class ABC {
    int a;
    public void getA() {return a;}
}
class XYZ extends ABC {
    int x;
    public void getX() {return x;}
}

编译器将这两个类加在一起:

class XYZ {
    int a;
    int x;
    public void getA() {return a;}
    public void getX() {return x;}
}

如果有任何其他可见性参数而不是公共,并且如果函数名或变量名之间存在重叠,那么它会比那更复杂,但基本上就是这样。在内存中,首先是基类的内容,然后是派生类的内容。

在内存中,你现在有类似这样的类(每个字母代表一个字节):

Class ABC: aaaa
Class XYZ: aaaaxxxx

所以当你访问这样的东西时:

ABC a1 = new XYZ();
a1.a = 5;

然后编译器将这个a1看作是一个ABC,它起作用,因为它们在对象的前四个字节中都有成员变量a。

但它不会让你做那样的事情:

ABC a1 = new XYZ();
a1.x = 5;

这是因为ABC的所有对象或其任何派生类型在前四个字节中都有成员变量a,但并非所有对象在后四个字节中都有x。只有XYZ的对象在后四个字节中具有x。因此编译器在此处抛出错误。

所以如果你写:

ABC a1 = new XYZ();

在内部看起来像这样:

a1 -> aaaaxxxx (reference a1 points to a structure containing 4 bytes a and 4 bytes x)

由于a1属于声明类型ABC(和动态类型XYZ),因此只能访问ABC中出现的成员变量(以及相应的字节)。因此,虽然有两个成员变量包含8个字节,但编译器只允许访问第一个成员变量(a)而不允许访问第二个成员变量。