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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 13:50:59  来源:igfitidea点击:

Protected variables can be accessed within Child Class or Child Object

javainheritanceprotected

提问by Santron Manibharathi

Is the protectedvariable of a parentObjectbe accessed from any child Object? or can be accessed only by only the particular childObject? I have a scenario which clearly expresses my doubt.

是否可以从任何孩子访问protecteda的变量?还是只能由特定的人访问?我有一个场景清楚地表达了我的怀疑。parentObjectObjectchildObject

I have two classes ParentClassand ChildClass. ParentClassis parent of ChildClass. I have a protectedvariable in ParentClassnamed protVar. It is of type Object. Then, I create two Objects like the following.

我有两个班级ParentClassChildClass. ParentClass是 的父级ChildClass。我protectedParentClassnamed 中有一个变量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 protVarof p1from c1?

现在我可以访问protVarof p1fromc1吗?

采纳答案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.

免责声明:答案复制自我对另一个问题的回答。但是,不接受该问题的答案。我相信它也适合这个问题,因此我正在将内容进行一些小的编辑复制到这里。

protectedis 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 Childextending Parent, and there is a protected member in Parent. What you can do in Childis 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 callMethodis declared in ChildClass, then NO, you cannot do it and it will not even compile. However if callMethodis declared in ParentClassthen everything is fine, because it is simply ParentClassaccessing protected member of a ParentClassinstance.

并且,具体到 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 Managerclass, manager.hireDayworks because manageris a primary expression, and the access is permitted because type of manageris Manageror subclass of Manager.

Manager类中,manager.hireDay之所以有效,manager是因为是主要表达式,并且允许访问,因为类型managerManager或子类Manager

So, based on JLS, why manager.hireDayworks 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);


     }
}