簡體   English   中英

可以在Child Class或Child Object中訪問受保護的變量

[英]Protected variables can be accessed within Child Class or Child Object

是否可以從任何子Object訪問parentObjectprotected變量? 或者只能由特定的childObject訪問? 我的情景清楚地表達了我的懷疑。

我有兩個類ParentClassChildClass ParentClassChildClass父級。 我在ParentClass有一個名為protVarprotected變量。 它是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()

現在我能從c1訪問p1protVar嗎?

免責聲明:答案是從我對另一個問題的回答中復制的。 但是,該問題沒有得到答案。 我相信它也適合這個問題,因此我將這些內容復制到這里進行一些小編輯。

protected在Java中有點有趣。 雖然我們總是說“protected”可以訪問不同包的子類,但它並不是全局。

舉例來說,如果你有Child伸出Parent ,並且在保護成員Parent 你能在做Child是訪問的受保護成員Child ,但甚至沒有保護的成員Parent 聽起來有點奇怪,雖然他們聽起來一樣嗎?

引自Core Java 9th Edition:

但是,Manager類方法只能查看Manager對象的hireDay字段,而不能查看其他Employee對象。 這種限制是為了使您不能通過形成子類來濫用受保護的機制,只是為了獲得對受保護字段的訪問

(類經理擴展了Employee,Employee中有一個hireDay受保護的成員,而Manager和Employee位於DIFFERENT包中)

例如,

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 ,那么NO,你不能這樣做,甚至不會編譯。 但是,如果在ParentClass聲明了callMethod ,那么一切都很好,因為它只是ParentClass訪問ParentClass實例的受保護成員。


更新:

鑒於評論中的批評,我認為值得去JLS看看它說的話:

(引自http://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.6.2.1關於訪問受保護成員,第二個子彈)

如果訪問是通過字段訪問表達式E.Id,或方法調用表達式E.Id(...),或方法引用表達式E :: Id,其中E是主表達式(第15.8節),那么當且僅當E的類型是S或S的子類時才允許訪問

這基本上就是我在答案中提供的內容:

Manager類, manager.hireDay可行的,因為manager是一個主表達,並且訪問被允許的,因為的類型managerManager或子類Manager

因此,基於JLS,為什么manager.hireDay工作DOESmanager類型(屬於同一類型)有關系。

是的,派生類可以通過'super'和對基類的另一個引用來訪問基類中的受保護變量。

編輯應該注意的是,我在這里假設相同的包,因為你沒有說明任何關於不同的包。 否則規則是不同的。

如果您的子類和Parent類在同一個包中,則可以直接訪問此對象[如果您願意],否則您有兩個選項。
1 - 在Parent類中創建一個公共getter方法,並使用該方法訪問受保護的字段
2 - Inside子類使用如下給出的反射獲取Parent protected字段

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();
    }
}

雖然這個問題很老,但我正在盡力解釋,因為這對java新手來說是一個相當普遍的問題。

考慮包p1中的Employee類。

package p1;
public class Employee{
    protected String hireDay = "hireday";
}

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類擴展了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)
    }*/
}

現在在root包中,我們有這個類來測試。

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);


     }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM