簡體   English   中英

從 package 外部的子類訪問受保護的變量

[英]Accessing a protected variable from a subclass outside package

我瀏覽了很多網站,這些網站解釋了 java 中的訪問說明符,例如java 論文java 的訪問說明符以及許多其他 stackoverflow 問題,例如這里

所有這些人都解釋說,受保護的成員可以被任何子類訪問(也可以被包外的子類訪問),並且可以被 package 級別的類訪問。

在對受保護成員進行試驗時,我發現我無法從 package 之外的子類訪問受保護成員。

檢查下面的代碼。 具有受保護成員的公共 class:

package com.One;

    public class ProVars {

    protected int i = 900;

    protected void foo()
    {
        System.out.println("foo");
    }

}

不同 package 中的另一個公共 class 試圖訪問受保護的成員:

package com.Two;

import com.One.ProVars;

public class AnotherClass extends ProVars {

    public static void main(String[] args) {
        ProVars p = new ProVars();
        System.out.println(p.i);//the field ProVars.i is not visible(Compilation Error)
                p.foo();//the method foo() from the type ProVars is not visible

    }
}

任何解釋表示贊賞。

你試圖使用它們,就好像它們是public 它們不是public ,它們受到protected

示例

ProVars p = new ProVars();
p.foo(); // This will throw an error because foo() is not public.

子類使用protected方法或變量的正確用法是:

public class MyClass extends ProVars
{
     public MyClass()
     {
           System.out.println(i); // I can access it like this.
           foo(); // And this.
     }
}

為什么這樣做?

因為你inherited了這個類。 這意味着您已經獲得了它的所有方法和變量。 現在,因為您的方法和變量是protected ,這也意味着它可以從subclass訪問。 嘗試將它們聲明為private ,看看會發生什么。

即使在派生類中,您也只能從至少屬於您自己類型的限定符訪問受保護的字段。

AnotherClass ,您可以訪問new AnotherClass().i ,但不能訪問new ProVars().i

如果您的主要方法不是靜態的,那就沒問題了。 靜態方法不關心繼承,因此您的“擴展 ProVars”將不起作用。 另一方面,這應該有效:

public class AnotherClass extends ProVars {

   public void accessProtected() {
       System.out.println(this.i);
       this.foo();
    }

    public static void main(String[] args) {
        AnotherClass p = new AnotherClass();
        p.accessProtected();
    }

}

與 Java保護訪問的混淆是由錯誤的教程引起的: https : //docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

甚至多次閱讀教程也沒有提供線索,為什么您不能從另一個包的另一個對象訪問Alpha類對象的受保護成員,其類AlphaSubAlpha的子類。

實際上,Java 語言規范對此進行了解釋,例如在 JLS 8 中:

6.6.2 受保護訪問的詳細信息

對象的受保護成員或構造函數可以從包的外部訪問,在該包中僅由負責實現該對象的代碼聲明它。

您需要更改行ProVars p = new ProVars(); 進入AnotherClass p = new AnotherClass();

否則,您仍然在創建 ProVars 類型的對象,編譯器將無法實現 AnotherClass 和 ProVars 之間的繼承(這會導致編譯錯誤)。

在您的main()使用子類:

public class AnotherClass extends ProVars {

    public static void main(String[] args) {
    AnotherClass p = new AnotherClass();
    System.out.println(p.i);
            p.foo();

}

}

當我們說它對子類可用時,我們的意思是它對子類代碼可用。 但是在您的示例中,您是從外部調用 protected 方法。

因此,雖然您的示例不起作用,但這應該

package com.Two;

import com.One.ProVars;

public class AnotherClass extends ProVars {

public static void main(String[] args) {
    ProVars p = new ProVars();
    p.test();
}

public test() {
        System.out.println(this.i);)
        this.foo();
}



}

您訪問變量的代碼位於靜態方法內 - 靜態方法不是繼承受保護字段的對象的直接一部分。

嘗試將代碼移動到您的 AnotherClass 類中的一個方法,然后從您的靜態方法中調用該方法。

在一個包中的類中聲明為 protected 的成員由子類繼承,子類可以位於該類的同一包中,也可以位於不同的包中。

**這里繼承是指在子類中可以使用超類的相同受保護成員,使用父引用和點運算符訪問如下將引發編譯錯誤。

ProVars p = new ProVars();
System.out.println(p.i);// error: i has protected access in parent

只需在您的子類中使用它:

System.out.println(i); // works fine, since subclass inherit the protected 
                          member of super class no matter whether they are in 
                          same or different package.

必須滿足兩個條件才能訪問超類中的受保護字段

1) 受保護並且只能在類的子類中在包點之外訪問

第二個總是被忽略

2) 它們是由訪問它們的代碼實現的對象字段。

請參閱此 JavaDocs https://docs.oracle.com/javase/specs/jls/se11/html/jls-6.html#jls-6.6.2

這是受保護的訪問修飾符的工作方式:

package a;

public class Fruit {
  protected int i = 5;
  protected void sayHello() {
    System.out.println("hello Fruit");
  }
}

現在像這樣導入上面的內容:

package b;
import a.Fruit;

public class Banana extends Fruit {
  public static void main(String[] args) {

    Banana banana = new Banana();
    System.out.println(banana.i);   // 5
    banana.sayHello();              // hello Fruit

    Fruit fruit = new Fruit();
    System.out.println(fruit.i);    // compile error
    fruit.sayHello();               // compile error

    Fruit fb = new Banana();
    System.out.println(fb.i);       // compile error
    fb.sayHello();                  // compile error
  }
}

您必須使用 inheritance 並且在第二種 package 方法中您必須使用 system.Out.Println(this.Protected);

在主要方法中使用創建 object 像 Demopackage obj = new Demopackage(); 對象保護

暫無
暫無

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

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