受保护的成员访问java中不同的包 – 一个好奇心

package packageOne; public class Base { protected void display(){ system.out.println("in Base"); } } package packageTwo; public class Derived extends packageOne.Base{ public void show(){ new Base().display();//this is not working throws compilation error that display() from the type Base is not visible new Derived().display();//is working display();//is working } } 

这两个包有两个不同的文件。 但为什么会这样呢?

http://java.sun.com/docs/books/jls/third_edition/html/names.html#6.6

 class C protected member; // in a different package class S extends C obj.member; // only allowed if type of obj is S or subclass of S 

动机可能如下。 如果objS ,则S类具有足够的内部知识,它有权操纵其成员,并且它可以安全地执行此操作。

如果obj不是S ,它可能是C另一个子类S2S不知道。 当写S时, S2可能甚至没有出生。 因为S操纵S2的受保护内部是非常危险的。 如果这是允许的话,从S2的角度来看,它不知道谁将篡改其受保护的内部以及如何,这使得S2工作很难推断自己的状态。

现在如果objD ,并且D extends S ,那么S访问obj.member是危险的吗? 不是真的。 S如何使用memberS及其所有子类(包括D )的共享知识。 S作为超类有权定义行为, D作为子类有义务接受和遵守。

为了便于理解,该规则应该真正简化为要求obj的(静态)类型正好是S 毕竟,子类D出现在S是非常不寻常和不合适的。 即使它发生了, obj的静态类型是D ,我们的简化规则可以通过向上转换轻松处理它: ((S)obj).member

protected允许从子类同一包中的其他类进行访问。 这就是为什么任何Derived类实例都可以访问Base的受保护方法。

另一行创建一个Base实例(不是Derived实例!!)。 并且只允许从同一个包的对象访问该实例的受保护方法。


 display(); 

– > 允许 ,因为调用者, Derived的实例可以访问受保护的成员及其子类的字段,即使它们位于不同的包中

 new Derived().display(); 

– > allowed ,因为您在Derived实例上调用该方法,并且该实例可以访问其子类的受保护方法

 new Base().display(); 

– > 不允许,因为调用者( this实例)类未在Base类中的同一个包中定义,因此无法访问受保护的方法。 并且 – 正如我们所看到的那样 – 当前从该包中对类进行子类化并不重要。 后门关闭;)

受保护的访问具有一些特殊规则,这些规则在Java语言规范中有详细说明:

受保护的成员或对象的构造函数可以从包外部访问,只能通过负责实现该对象的代码来声明它。

 new Base().display(); 

它创建一个Base对象,然后trys调用它上面的display()。
显然它不起作用,因为Base上的display()受到保护。

首先想到的是你可以在任何ware中使用protected Object ,但只有不同的包非子类不能从其他类访问受保护的成员。 这意味着你无法直接使用它。 首先你得到那个obj然后使用。

  package Demos; public class AB { public int a = 14; protected int b = 13; } 

我们还有另一个类

 package Example; import Demos.AB; public class Ex1 extends AB { public static void main(String[] args) { AB obj = new AB(); // obj of AB OR // AB obj = new Ex1(); object of Ex1 but referance of AB // cant use protacted member System.out.println(obj.a); System.out.println(obj.b); //You can't use Ex1 obj1 = new Ex1(); // you have to make obj of sub-class referance of Ex1 System.out.println(obj1.a); System.out.println(obj1.b); // Now You can use } } 

在这个问题上你必须扩展受保护成员的类,然后使用你不能直接使用。

这是预期的行为。 protected表示inheritance的类和相同的包类可以看到该方法。 所以,这就是你所看到的。

这可能是你问题的直接答案,但我认为没有理由你会调用new Base().display(); 。 也许你在super.display();意思super.display();

在这种情况下,您实际上使用的是inheritance的方法,但仅仅因为您inheritance了一个类,并不意味着您可以访问受保护的方法(根据定义,这些方法只对超类可见)。

区别在于您尝试从您inheritance的类的实例访问受保护方法的一种情况(您的示例)。 在我的示例中,您可以通过inheritance访问受保护的方法。

总结:您可以通过inheritance上下文访问该方法。

为什么?

它为程序员提供了灵活性,可以决定哪些function只能由直接后代使用或扩展。

受保护的成员或对象的构造函数可以从包外部访问,只能通过负责实现该对象的代码来声明它。

display不是Base里面的静态方法。 因此,您必须首先创建Base实例,然后调用display。

 Base base = new Base(); base.display();