Java 当使用公共getter从子类访问时,超类的私有字段位于何处?
不作为重复说明此问题地址字段位于程序中的何处不是继承的还是未继承的,或者是继承的但不可访问的 请继续阅读理解 在下面的示例中,我们看到dog对象可以访问动物私有字段“name”,但不能使用公共getter“getName”,因为私有字段没有被继承,所以字段名所在的位置 通过搜索,我意识到只有一个对象是从子类创建的,而不是两个对象,一个是子类,一个是超级类,用来保存私有字段 现在关注>>我们都知道,任何类中的公共setter都可以设置其私有字段,但我们知道字段所在的位置!在类的对象中 因此,我的抽象问题如下 访问的私有字段位于创建的子类对象中强> 它在哪里Java 当使用公共getter从子类访问时,超类的私有字段位于何处?,java,Java,不作为重复说明此问题地址字段位于程序中的何处不是继承的还是未继承的,或者是继承的但不可访问的 请继续阅读理解 在下面的示例中,我们看到dog对象可以访问动物私有字段“name”,但不能使用公共getter“getName”,因为私有字段没有被继承,所以字段名所在的位置 通过搜索,我意识到只有一个对象是从子类创建的,而不是两个对象,一个是子类,一个是超级类,用来保存私有字段 现在关注>>我们都知道,任何类中的公共setter都可以设置其私有字段,但我们知道字段所在的位置!在类的对象中 因此,我的抽
public class Animal {
private String name ;
public Animal (String name)
{
this.name = name;
}
public String getName()
{
return this.name;
}
}
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
}
public class Hello {
public static void main(String[] args) {
Dog mmms = new Dog("mmkk");
System.out.println(mmms.getName());
}
}
编辑:我认为这个问题可以表述为
如果父类没有继承,它的私有字段在哪里?
问题名称已更改,以便进一步了解
子类对象如何从公共getter访问其超类的私有成员
到
当使用公共getter从子类访问时,超级类的私有字段在哪里生存?只有一个
Dog
实例,它也包含name
实例变量,因为Dog
是动物,尽管该字段没有正确地从实例中存在的父类
让你不安的是,name
不能直接从Dog
code访问,但它确实存在。它只是为了保护封装
但是,您可以使用动物的公共或受保护方法读取或修改此值,如getName()
所做的,或者您可以使用来实现此目标:
Dog dog= new Dog("mmmk");
Field name = Animal.class.getDeclaredField("name");
name.setAccessible(true);
name.set(dog, "xxxxx");
System.err.println(dog.getName());
现在您可以看到,name
的值已被修改为“xxxxx”每当创建子类的实例时,即Dog的实例时,都会按顺序调用所有父类的构造函数,分配存储完整链状态所需的空间。在您的例子中,超级构造函数是显式调用的,但即使没有显式调用,也会进行隐式调用,前提是有一个默认构造函数(如果没有,则代码不会编译)
有关父实例状态的信息可用,并与子实例一起存储。存储此信息的方式取决于JVM实现,Oracle JRE与OpenJRE不同。但是,这并不重要,重要的是子级可能无法访问父级的字段或方法(对于私有字段或方法),但所有字段都存在并分配了一个值,至少是一个默认值。所有方法也都存在,并根据vtable
:
实例方法被分派到与定义类相对应的实例部分。因此,在您的案例中,如果类动物
定义了getName
和setName
一个在前往Dog
的途中没有父对象的类重新定义了它们,那么JRE将以与动物
相对应的部分维护的状态执行代码,从而设置或检索存储在那里的名称
。同时,所有Java方法(包括private)都是虚拟的,因此可以在子类中重写。有关此类覆盖的信息将保留在负责调度的vtable
中。因此,如果您的类Dog
重新定义getName
和setName
以执行其他操作(它将无法从该类定义访问name
字段),然后在Dog
的实例上调用这些方法实际上将调用Dog
中定义的方法,而不是Animal
。在这种情况下,您可能会失去对Animal
中的name
字段的任何访问权限(除非在Animal
中定义了其他getter/setter),即使您在构造函数中放置的值将保持存储状态
正如其他地方所指出的,仍然可以通过反射或字节码操作访问私有信息,但这可能很少或出于非常特殊的原因(例如,私有字段上的@Inject
注释可能导致通过某个注入框架设置值)。即使可以这样做,通过反射访问私有隐藏(私有、受保护、包可见)方法或字段也应该是一个例外,而不是常见的做法,因为它显然违反了最初的设计决策
进一步阅读:
调用super(name)时,在Animal
类中设置字段
在Dog
类中,我知道是这样做的,但它在我的对象中的位置不是继承的还是继承的?我的问题集中在哪里,而不是我是如何做到的,但最好解释一下子类的两个对象都包含超类的私有字段。所以从某种意义上说,它们是遗传的,你只是不能在子类中访问它们。不,如果你读得好,这是不一样的。你看,我是说,如果它是继承的,它不是在哪里。这是一个愚蠢的问题。谢谢解释。你有一篇文章解释了虚拟机是如何做到这一点的吗more@Sam我将尝试找到一个,但我可以确定该字段是继承的。它和其他领域一样存在。除非您使用反射,否则它是不可访问的。@Sam事实上,我已经阅读了作为副本提供的链接,但有一点细微差别:该字段不是从父类继承的,而是从父类继承的