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

在JAVA中,当基类的引用变量指向子类的对象时,内部会发生什么,java,class,object,inheritance,reference,Java,Class,Object,Inheritance,Reference,ABC a1=new XYZ() 其中XYZ扩展了ABC 数据类型告诉我们变量将包含什么。 让我困惑的是,怎么可能要求引用变量指向它不是变量的东西 即使我们能做到,它有什么好处 它是如何在内部工作的。当我们写作时 ABC a1=new XYZ()此模式为您提供了灵活性 排序算法示例: private List<Integer> myCollectionToSort = new ArrayList<>(); 就这样想吧: ABC a1 = new XYZ(); a1.a

ABC a1=new XYZ()
其中XYZ扩展了ABC

数据类型告诉我们变量将包含什么。

让我困惑的是,怎么可能要求引用变量指向它不是变量的东西

即使我们能做到,它有什么好处

它是如何在内部工作的。当我们写作时
ABC a1=new XYZ()

此模式为您提供了灵活性

排序算法示例:

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

就这样想吧:

ABC a1 = new XYZ();
a1.a = 5;
a1 -> aaaaxxxx (reference a1 points to a structure containing 4 bytes a and 4 bytes x)
鉴于这两类:

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;}
}
如果存在除public之外的任何其他可见性参数,如果函数名或变量名之间存在重叠,那么它就要稍微复杂一点,但基本上就是这样。在内存中,首先是基类的内容,然后是派生类的内容

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

因此,当您访问以下内容时:

ABC a1 = new XYZ();
a1.a = 5;
a1 -> aaaaxxxx (reference a1 points to a structure containing 4 bytes a and 4 bytes x)
然后,编译器将此a1视为一个ABC,这是有效的,因为两者的成员变量a都位于对象的前四个字节中

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

ABC a1 = new XYZ();
a1.x = 5;
这是因为ABC的所有对象或其任何派生类型的前四个字节中都有成员变量a,但并非所有对象的后四个字节中都有x。只有XYZ的对象在第二个四字节中有x。因此,编译器在这里抛出一个错误

所以如果你写:

ABC a1 = new XYZ();
内部看起来是这样的:

ABC a1 = new XYZ();
a1.a = 5;
a1 -> aaaaxxxx (reference a1 points to a structure containing 4 bytes a and 4 bytes x)

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

“要指出的是,它不是“->的变量,是的。这是一个非常广泛的问题。例如,请阅读关于多态性的文章,看看有哪些可能的好处。@ArnaudDenoyelle如何?@BartoszKP哦,是的,我可以设法消化这些好处。但我想知道会发生什么internally@SrujanBarai为了说明为什么
XYZ
ABC
,我完成了我的回答。