受保护的成员访问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
动机可能如下。 如果obj
是S
,则S
类具有足够的内部知识,它有权操纵其成员,并且它可以安全地执行此操作。
如果obj
不是S
,它可能是C
另一个子类S2
, S
不知道。 当写S
时, S2
可能甚至没有出生。 因为S
操纵S2
的受保护内部是非常危险的。 如果这是允许的话,从S2
的角度来看,它不知道谁将篡改其受保护的内部以及如何,这使得S2
工作很难推断自己的状态。
现在如果obj
是D
,并且D extends S
,那么S
访问obj.member
是危险的吗? 不是真的。 S
如何使用member
是S
及其所有子类(包括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();