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
不起作用,因为