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
}
}
这两个包有两个不同的文件。但为什么会这样呢?
答案 0 :(得分:14)
protected
允许从同一包中的其他类访问子类和。这就是为什么任何Derived
类实例都可以访问Base
中的受保护方法。
另一行创建Base
实例(不是Derived
实例!!)。并且只允许从同一个包的对象访问该实例的受保护方法。
display();
- > 允许,因为调用者,Derived
的实例可以访问受保护的成员及其子类的字段,即使它们位于不同的包中
new Derived().display();
- > 允许,因为您在Derived
的实例上调用该方法,并且该实例可以访问其子类的受保护方法
new Base().display();
- > 不允许因为调用者(this
实例)类未在Base
类的同一个包中定义,因此this
无法访问受保护的类方法。并且 - 正如我们所看到的那样 - 当前从该包中对类进行子类化并不重要。 后门已关闭;)
答案 1 :(得分:3)
受保护的访问权限有一些特殊规则,详见Java Language Specification:
对象的受保护成员或构造函数可以从包外部访问,只能通过负责实现该对象的代码来声明它。
答案 2 :(得分:3)
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
,则可能是S2
的另一个子类C
,S
根本不知道。撰写S2
时,S
可能甚至没有出生。 S
操纵S2
受保护的内部是非常危险的。如果允许这样做,从S2
的角度来看,它不知道谁将篡改其受保护的内部以及如何,这使得S2
很难对自己的状态进行推理。< / p>
如果obj
为D
和D extends S
,S
访问obj.member
会有危险吗?并不是的。 S
使用member
的方式是S
及其所有子类的共享知识,包括D
。 S
因为超类有权定义行为,D
因为子类有义务接受和遵守。
为了便于理解,该规则应该简化为要求obj
的(静态)类型正好S
。毕竟,子类D
出现在S
中是非常不寻常和不合适的。即使它发生了,obj
的静态类型是D
,我们的简化规则也可以通过向上转换轻松处理它:((S)obj).member
答案 3 :(得分:1)
new Base().display();
它创建一个Base对象,然后尝试调用它上面的display()。
答案 4 :(得分:1)
首先想到的是,您可以在任何商品中使用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
}
}
在这个问题上你必须扩展受保护成员的类然后使用你不能直接使用。
答案 5 :(得分:0)
这是预期的行为。 protected表示继承的类和相同的包类可以看到该方法。所以,这就是你所看到的。
答案 6 :(得分:0)
这可能是您问题的直接答案,但我认为没有理由为您致电新Base().display();
。也许你在super.display();
中的意思。
在这种情况下,您实际上是在使用继承的方法,但仅仅因为您继承了一个类,并不意味着您可以访问 类 受保护的方法(根据定义,只对超类可见)。
区别在于您尝试从您继承的类的实例访问受保护方法的一种情况(您的示例)。在我的示例中,您可以通过继承访问受保护的方法。
总结:您可以通过继承上下文访问该方法。
为什么?
它为程序员提供了灵活性,可以决定哪些功能只能由直接后代使用或扩展。
答案 7 :(得分:0)
对象的受保护成员或构造函数可以从包外部访问,只能通过负责实现该对象的代码来声明它。
答案 8 :(得分:-1)
display
不是Base中的静态方法。因此,您必须首先创建一个Base实例,然后调用display。
Base base = new Base();
base.display();