Java 可以在子类或子对象中访问受保护的变量
是否可以从任何子对象访问父对象的受保护变量?或者只能由特定的Java 可以在子类或子对象中访问受保护的变量,java,inheritance,protected,Java,Inheritance,Protected,是否可以从任何子对象访问父对象的受保护变量?或者只能由特定的子对象访问?我有一个场景清楚地表达了我的怀疑 我有两个类ParentClass和ChildClassParentClass是ChildClass的父类。我在ParentClass中有一个名为protVar的protected变量。它属于对象类型。然后,我创建两个对象s,如下所示 ParentClass p1 = new ParentClass(); ChildClass c1 = new ChildClass(); c1.callMet
子对象访问?我有一个场景清楚地表达了我的怀疑
我有两个类ParentClass
和ChildClass
ParentClass
是ChildClass
的父类。我在ParentClass
中有一个名为protVar
的protected
变量。它属于对象类型
。然后,我创建两个对象
s,如下所示
ParentClass p1 = new ParentClass();
ChildClass c1 = new ChildClass();
c1.callMethod(p1); // Here I want to access protected variable of p1 which is a separate object and Not initialized within c1 as super()
现在我可以从c1
访问p1
的protVar
?是的,派生类可以通过“super”和对基类的另一个引用访问基类中的受保护变量
编辑应该注意的是,我在这里假设的是同一个包,因为您没有说明任何关于不同包的内容。否则规则不同。如果您的子类和父类位于同一个包中,则您可以直接访问此对象[如果愿意],否则,您有两个选择。
1-在父类中创建一个公共getter方法,并使用该方法访问受保护的字段
2-在子类内部使用下面给出的反射获取受保护的父字段
public void callMethod(ParentClass o) {
try {
Field f = o.getClass().getDeclaredField("protVar");
f.setAccessible(true);
Object value = f.get(o);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
免责声明:答案来自。然而,这个问题的答案不被接受。我相信它也适合这个问题,因此我复制了一些小编辑到这里的内容
protected
在Java中有点有趣。虽然我们总是说“protected”允许访问不同包的子类,但这并不是全部
例如,如果您有子级
扩展父级
,并且在父级
中有一个受保护的成员。您可以在Child
中访问Child
的受保护成员,但即使是Parent
的受保护成员也不能访问。听起来有点奇怪,对吧,虽然它们听起来是一样的
引用自核心Java第9版:
但是,管理器类方法可以窥视hireDay字段内部
仅适用于经理对象,不适用于其他员工对象。这
设置了限制,这样您就不会滥用受保护的机制
形成子类只是为了访问受保护的字段
(类经理扩展了Employee,Employee中有一个hireDay受保护的成员,经理和员工位于不同的包中)
比如说,
public class Manager extends Employee {
// accessing protected member of itself
public void foo1() {
System.out.println("" + this.hireDay); // OK
}
// access protected member of instance of same type
public void foo2(Manager manager) {
System.out.println("" + manager.hireDay); // OK
}
// access protected member of instance of super-class
public void foo3(Employee employee) {
System.out.println("" + employee.hireDay); // NOT ALLOWED!
}
}
这意味着,受保护的成员允许来自另一个包的子类通过该子类的引用进行访问(或者this
,或者是另一个子类引用)
并且,具体到OP的回答:如果在ChildClass
中声明了callMethod
,那么不,您不能这样做,它甚至不会编译。但是,如果在ParentClass
中声明了callMethod
,则一切都正常,因为它只是访问ParentClass
实例的受保护成员
更新:
鉴于评论中的批评,我认为值得去JLS看看它说了什么:
(引自关于访问受保护构件的第二个项目符号)
如果访问是通过字段访问表达式E.Id或方法进行的
调用表达式E.Id(…),或方法引用表达式E::
Id,其中E是主表达式(§15.8),则访问
当且仅当E的类型为S或S的子类时才允许
这基本上就是我在回答中试图表达的:
在Manager
类中,Manager.hireDay
工作是因为Manager
是一个主要表达式,并且允许访问是因为Manager
的类型是Manager
或Manager
的子类
因此,基于JLS,为什么manager.hireDay
works与manager
(属于同一类型)的类型有关系。即使这个问题很老,我还是尽力解释,因为这对于java新手来说是一个相当常见的问题
考虑包p1中的Employee类
package p1;
public class Employee{
protected String hireDay = "hireday";
}
经理扩展了员工,并且位于不同的包中
package p2;
public class Manager extends p1.Employee {
//now even Manager class has hireDay protected variable that was defined in Employee class.
//Since Manager class has protected variable hireDay , for any manager m1 , we can access hireDay as m1.hireDay ONLY within package p2.
}
Enterprenur类扩展了Manager,位于p3包中
package p3;
public class Enterpreneur extends p2.Manager{
//now Enterpreneur class has inherited hireDay protected variable that Employee class had. (see comments in Employee class.)
//Since Enterpreneur class has protected variable hireDay , for any Enterpreneur e , we can access hireDay as e.hireDay ONLY within package p3.
//the following will work because using Enterpreneur reference e , we can access e.hireday within package p3 , this has nothing to do with
//the fact that right now our code is present in Enterpreneur class , like the other answer said. Note the method is static.
public static void printhireDay(Enterpreneur e){
System.out.println("hireday is :" + e.hireDay);
}
//this will work because using this reference we can only access protected variable in the same class(Enterpreneur) or in a subclass.
public void printhireDay(){
System.out.println("hireday is :" + this.hireDay);
}
// This shouldn't work because using manager reference , we can only access protected field within package p2.
/* public printhireDay(Manager m){
System.out.println("hireday is :" + m.hireDay)
}*/
}
现在在根包中,我们有这个类要测试
public class HelloWorld{
public static void main(String []args){
p3.Enterpreneur e = new p3.Enterpreneur();
//both of these work.
e.printhireDay();
//printing by passing the reference e.
p3.Enterpreneur.printhireDay(e);
}
}
你可以在子类中访问超级类的受保护变量真的很难尝试吗?你想尝试什么也不清楚。在子类中传递父类的对象。@EJP我只想知道除了试错模式之外还有什么技术解释。@Youngistan这不是手机。请努力正确加快速度,并在总体上写出清晰的标准英语.Ui。很抱歉,这根本不是真的!受保护的成员(字段或方法)只能通过超级机制访问。如果您以另一种方式获得引用,则您只能在同一个包中访问此成员(因为受保护还包括包可见性)!我相信EJP和@SeelenVirtuse都是错误的。最近我回答了一个类似的问题:不,我没有错。不能从仅具有引用的对象(例如,通过简单变量)访问受保护字段。但请记住,只有当您的访问代码驻留在另一个包中时,这才是正确的。如果是同一个包,您可以访问受保护的字段,因为受保护包括包可见性。非常奇怪的是,您都认为这是不正确的。我在发布之前测试了它。方法ChildClass.method(ParentClass p)
可以访问p.protectedVariable。
@Radiodef关于不同包的问题没有任何内容。答案是误导性的。在第二部分中,manager.hireDay
不起作用,因为