Java 可以在子类或子对象中访问受保护的变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22139513/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Protected variables can be accessed within Child Class or Child Object
提问by Santron Manibharathi
Is the protected
variable of a parentObject
be accessed from any child Object
? or can be accessed only by only the particular childObject
? I have a scenario which clearly expresses my doubt.
是否可以从任何孩子访问protected
a的变量?还是只能由特定的人访问?我有一个场景清楚地表达了我的怀疑。parentObject
Object
childObject
I have two classes ParentClass
and ChildClass
. ParentClass
is parent of ChildClass
. I have a protected
variable in ParentClass
named protVar
. It is of type Object
. Then, I create two Object
s like the following.
我有两个班级ParentClass
和ChildClass
. ParentClass
是 的父级ChildClass
。我protected
在ParentClass
named 中有一个变量protVar
。它的类型为Object
。然后,我创建两个Object
如下所示。
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()
Now will I be able to access the protVar
of p1
from c1
?
现在我可以访问protVar
of p1
fromc1
吗?
采纳答案by Adrian Shum
Disclaimer: the answer is copied from my answer of another question. However no answer from that question is accepted. I believe it also suit this question therefore I am copying the content with some minor editing to here.
免责声明:答案复制自我对另一个问题的回答。但是,不接受该问题的答案。我相信它也适合这个问题,因此我正在将内容进行一些小的编辑复制到这里。
protected
is a bit interesting in Java. Although we always says "protected" give access to subclass of different package, it is not the whole picture.
protected
在 Java 中有点有趣。尽管我们总是说“受保护”可以访问不同包的子类,但这并不是全部。
For example, if you have Child
extending Parent
, and there is a protected member in Parent
. What you can do in Child
is to access that protected member of Child
, but not even that protected member of Parent
. Sounds a bit strange right although they sounds the same thing?
例如,如果您有Child
扩展Parent
,并且在Parent
. 您可以做的Child
是访问 的受保护成员Child
,但甚至不能访问 的受保护成员Parent
。听起来有点奇怪,虽然它们听起来是一样的?
Quoted from Core Java 9th Edition:
引自 Core Java 9th Edition:
However, the Manager class methods can peek inside the hireDay field of Manager objects only, not of other Employee objects. This restriction is made so that you can't abuse the protected mechanism by forming subclasses just to gain access to the protected fields
但是,Manager 类方法只能查看 Manager 对象的hiringDay 字段内部,而不能查看其他 Employee 对象的内部。制定此限制是为了您不能通过形成子类来滥用受保护机制,只是为了获得对受保护字段的访问权限
(class Manager extends Employee, and there is a hireDay protected member in Employee, and Manager and Employee are located in DIFFERENTpackage)
(Manager类继承了Employee,Employee中有一个hireDay保护的成员,Manager和Employee位于DIFFERENT包中)
For example,
例如,
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!
}
}
Which means, protected member allow child class from another package to access through reference of that child class (either this
, or another reference that is-a child class)
这意味着,受保护的成员允许来自另一个包的子类通过该子类的引用(或者this
,或另一个子类的引用)进行访问
And, be specific to OP's answer: if callMethod
is declared in ChildClass
, then NO, you cannot do it and it will not even compile. However if callMethod
is declared in ParentClass
then everything is fine, because it is simply ParentClass
accessing protected member of a ParentClass
instance.
并且,具体到 OP 的答案:如果callMethod
在 中声明ChildClass
,那么不,你不能这样做,它甚至不会编译。但是,如果callMethod
声明在ParentClass
那么一切都很好,因为它只是ParentClass
访问ParentClass
实例的受保护成员。
Update:
更新:
Given criticisms in comment, I think it worth to go to JLS to see what it say:
鉴于评论中的批评,我认为值得去 JLS 看看它说了什么:
(Quoted from http://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.6.2.1about Access to a protected Member, second bullet)
(引自http://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.6.2.1关于访问受保护成员,第二个要点)
If the access is by a field access expression E.Id, or a method invocation expression E.Id(...), or a method reference expression E :: Id, where E is a Primary expression (§15.8), then the access is permitted if and only if the type of E is S or a subclass of S
如果通过字段访问表达式 E.Id、方法调用表达式 E.Id(...) 或方法引用表达式 E::Id 进行访问,其中 E 是主表达式(第 15.8 节),则当且仅当 E 的类型是 S 或 S 的子类时才允许访问
This is essentially what I was trying to deliver in the answer:
这基本上是我试图在答案中提供的内容:
Within Manager
class, manager.hireDay
works because manager
is a primary expression, and the access is permitted because type of manager
is Manager
or subclass of Manager
.
在Manager
类中,manager.hireDay
之所以有效,manager
是因为是主要表达式,并且允许访问,因为类型manager
是Manager
或子类Manager
。
So, based on JLS, why manager.hireDay
works DOEShave relationship with type of manager
(being the same type).
因此,基于JLS,为什么manager.hireDay
工作DOES有型的关系manager
(即同一类型)。
回答by user207421
Yes, a derived class can access a protected variable in a base class via both 'super' and another reference to the base class.
是的,派生类可以通过“super”和对基类的另一个引用访问基类中的受保护变量。
EDITIt should be noted that I am here assuming the same package as you didn't state anything about different packages. The rules are different otherwise.
编辑应该注意的是,我在这里假设相同的包,因为您没有说明关于不同包的任何内容。否则规则不同。
回答by Naveen Ramawat
If your child class and Parent class in same package than you can access this object directly [If you wish], Otherwise you have two option.
1 - Create a public getter method in Parent class and access your protected field using that method
2 - Inside child class fetch the Parent protected field using reflection like given below
如果你的子类和父类在同一个包中,你可以直接访问这个对象[如果你愿意],否则你有两个选择。
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();
}
}
回答by Rpant
Even though the question is old , I am trying my best to explain , since this is a fairly common question for java newbies.
尽管这个问题很老,但我尽力解释,因为这对于 Java 新手来说是一个相当普遍的问题。
Consider Employee class in package p1.
考虑包 p1 中的 Employee 类。
package p1;
public class Employee{
protected String hireDay = "hireday";
}
Manager extends Employee and is in a different package.
Manager 扩展了 Employee 并且位于不同的包中。
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 class extends Manager and is in package p3.
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)
}*/
}
Now within the root package , we have this class to test.
现在在根包中,我们有这个类要测试。
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);
}
}