Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么子类是';存储在超类类型变量中时是否保留私有变量?_Java_Inheritance_Subclass_Superclass - Fatal编程技术网

Java 为什么子类是';存储在超类类型变量中时是否保留私有变量?

Java 为什么子类是';存储在超类类型变量中时是否保留私有变量?,java,inheritance,subclass,superclass,Java,Inheritance,Subclass,Superclass,我肯定错过了一些基本的继承,因为它对我来说没有意义 鉴于这两类: class Person { private String name; } class Student extends Person { private String degree; } 为什么可以创建一个新的Student对象,将其存储在Person类型变量中,并且仍然能够保留变量字符串度并访问它 Person p = new Student("John", "Master's"); 我认为可以使用上面的初始化

我肯定错过了一些基本的继承,因为它对我来说没有意义

鉴于这两类:

class Person
{
   private String name;
}

class Student extends Person
{
   private String degree;
}
为什么可以创建一个新的
Student
对象,将其存储在
Person
类型变量中,并且仍然能够保留变量
字符串度并访问它

Person p = new Student("John", "Master's");
我认为可以使用上面的初始化,因为
p
除了
name
之外没有任何变量,因为
Person
变量不能包含
degree
变量,因此它是合法的-但是当您这样做时,
p
中不存在
degree

这就是我所认为的原因,相反的事物是非法的

Student s=newperson(“John”);
)-因为这样
s
就不会初始化它的另一个变量(
degree
)。

具有超类型引用类型的变量可以包含子类型实例的引用。将子类型实例指定给变量不会以任何方式更改实例;它只是拓宽了参考的类型。所有实例数据仍然存在,并且可以通过向下转换进行检索。就是

Student s = new Student("John", "Master's");
Person p = s; // no cast needed for a widening conversion
与以下内容完全相同:

Person p = new Student("John", "Master's");
Student s = (Student) p; // cast required for a narrowing conversion
编辑也许这有助于澄清问题。 假设有第二个子类
Person

class Teacher extends Person
{
    private String department;
}
现在您可以执行以下操作:

Person p = new Teacher("Fred", "Physics");
Teacher t = (Teacher) p;
但如果您以后尝试这样做:

p = new Teacher("Fred", "Physics");
Student s = (Student) p; // Error!
您将得到一个,因为在程序中的这一点上,
p
现在是对一个对象的引用(
Teacher
),该对象不是
Student

这里有一个类比。在英语中,你可能会说,“我有一只宠物动物”。这与动物的类型无关。(例如,你无法知道宠物是否会吠叫。)另一方面,如果你说“我有一只宠物狗”,那么问它是否会对陌生人吠叫是有道理的。关键是:称你的宠物为动物并不能改变它是(或不是)狗的事实。使用更通用(例如,基类)的引用类型来存储对象引用不会改变对象本身的性质。您失去了对对象细节的了解,但这些细节仍然存在


重复我在评论中提出的观点:在Java中,您从不将对象分配给变量;只能将引用指定给对象。或者,换句话说,您的变量都不是对象。

具有超类型引用类型的变量可以包含对子类型实例的引用。将子类型实例指定给变量不会以任何方式更改实例;它只是拓宽了参考的类型。所有实例数据仍然存在,并且可以通过向下转换进行检索。就是

Student s = new Student("John", "Master's");
Person p = s; // no cast needed for a widening conversion
与以下内容完全相同:

Person p = new Student("John", "Master's");
Student s = (Student) p; // cast required for a narrowing conversion
编辑也许这有助于澄清问题。 假设有第二个子类
Person

class Teacher extends Person
{
    private String department;
}
现在您可以执行以下操作:

Person p = new Teacher("Fred", "Physics");
Teacher t = (Teacher) p;
但如果您以后尝试这样做:

p = new Teacher("Fred", "Physics");
Student s = (Student) p; // Error!
您将得到一个,因为在程序中的这一点上,
p
现在是对一个对象的引用(
Teacher
),该对象不是
Student

这里有一个类比。在英语中,你可能会说,“我有一只宠物动物”。这与动物的类型无关。(例如,你无法知道宠物是否会吠叫。)另一方面,如果你说“我有一只宠物狗”,那么问它是否会对陌生人吠叫是有道理的。关键是:称你的宠物为动物并不能改变它是(或不是)狗的事实。使用更通用(例如,基类)的引用类型来存储对象引用不会改变对象本身的性质。您失去了对对象细节的了解,但这些细节仍然存在

重复我在评论中提出的观点:在Java中,您从不将对象分配给变量;只能将引用指定给对象。或者,换一种说法,您的变量都不是对象。

变量不包含对象。变量包含标识对象的引用。如果有一个汽车识别号列表(美国的VIN),该列表本身可能包含许多不同种类的汽车的编号;从列表的角度来看,每个号码都可以识别一辆车,但一个号码可能会识别福特福克斯,另一个是丰田,另一个是雪佛兰敞篷车等等。如果在列表上写下雪佛兰敞篷车的号码,列表将不知道它是一辆敞篷车,因此无法说明“在列表中第五辆车上升起车顶”,但不首先确定第五个VIN标识的车具有活顶。车顶不会是在确定该车为活顶时出现的;车顶及其状态(升起或降下)无论谁知道它们,都将继续存在。

变量不包含对象。变量包含标识对象的引用。如果有汽车识别号列表(美国的VIN),列表本身可能包含许多不同种类的汽车的编号;从列表的角度来看,每个编号都可以识别一辆汽车,但一个编号可以识别FordFocus,另一个编号可以识别ToyotaPrius,另一个编号可以识别ChevroletSebringConvertive,等等。如果将ChevroletSebringConvertive的编号写在列表上,则列表将显示不知道这是一辆敞篷车,因此如果不首先确定第五个VIN标识的汽车有一个敞篷车,就不能说“在列表中的第五辆汽车上升起车顶”。车顶不是在汽车被标识为敞篷车时出现的;车顶及其状态(升起或降下)无论谁知道它们,它们都会继续存在。

所以即使