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
}
}
这两个包位于两个不同的文件中。但为什么会有这种行为呢?
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
}
}
The two packages are in two different files. But why this behaviour?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
这可能是对您问题的直接回答,但我认为您没有理由调用 new
Base().display();
。也许你的意思是super.display();
。在这种情况下,您实际上正在使用继承的方法,但仅仅因为您继承了一个类,并不意味着您可以访问类受保护的方法(根据定义,仅对超类可见)。
区别在于,在一种情况(您的示例)中,您尝试从您继承的类的实例访问受保护的方法。在我的示例中,您可以通过继承访问受保护的方法。
总之:您可以通过继承上下文访问该方法。
为什么?
它使程序员可以灵活地决定哪些功能只能由直系后代使用或扩展。
This might be a direct answer to your question, but i see no reason why you would call new
Base().display();
. Perhaps what you mean insuper.display();
.In this case, you are actually using the inherited method, but just because you're inheriting a class, it doesn't mean that you access to the class protected methods (which by definition are only visible to super classes).
The difference is on one case (your example) you're trying to access a protected method from an instance of a class that you inherited. In my example, you can access the protected method through inheritance.
In summary: you can access the method through inheritance context.
Why?
It gives programmers flexibility in deciding which features can only be used or extended by direct descendants.
对象的受保护成员或构造函数可以从包外部访问,在包中只能由负责实现该对象的代码来声明它。
A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object.
display
不是 Base 内部的静态方法。所以,你必须先创建一个Base实例,然后调用display。display
is not a static method inside Base. So, you have to first create an instance of Base and then call display.protected
允许子类和同一包中的其他类进行访问。这就是为什么任何Derived
类实例都可以访问Base
中受保护的方法。另一行创建一个
Base
实例(不是Derived
实例!!)。并且只允许来自同一包的对象访问该实例的受保护方法。-> 允许,因为调用者,
Derived
的实例可以访问其子类的受保护成员和字段,即使它们位于不同的包中-> 允许,因为您在
Derived
实例上调用该方法,并且该实例可以访问其子类的受保护方法-> 不允许,因为调用者的(
this
实例)类没有像Base
类一样定义在同一个包中,所以this< /code> 无法访问受保护的方法。正如我们所看到的,当前从该包中继承一个类并不重要。该后门已关闭;)
protected
allows access from subclasses and from other classes in the same package. That's why anyDerived
class instance can access the protected method inBase
.The other line creates a
Base
instance (not aDerived
instance!!). And access to protected methods of that instance is only allowed from objects of the same package.-> allowed, because the caller, an instance of
Derived
has access to protected members and fields of its subclasses, even if they're in different packages-> allowed, because you call the method on an instance of
Derived
and that instance has access to the protected methods of its subclasses-> not allowed because the caller's (the
this
instance) class is not defined in the same package like theBase
class, sothis
can't access the protected method. And it doesn't matter - as we see - that the current subclasses a class from that package. That backdoor is closed ;)http://java.sun.com/docs/books /jls/third_edition/html/names.html#6.6
动机大概如下。如果
obj
是一个S
,类S
对其内部有足够的了解,它有权操作它的成员,并且它可以做到这一点安全。如果
obj
不是S
,它可能是C
的另一个子类S2
,其中S
代码> 不知道。当S
被写入时,S2
可能还没有诞生。对于S
来说,操纵S2
受保护的内部结构是相当危险的。如果允许这样做,从S2
的角度来看,它不知道谁会篡改其受保护的内部结构以及如何篡改,这使得S2
工作很难推理关于它自己的状态。现在,如果
obj
是D
,并且D扩展了S
,那么S
访问obj是否危险? .member
?并不真地。S
如何使用member
是S
及其所有子类(包括D
)的共享知识。S
作为超类有定义行为的权利,而D
作为子类有接受和遵守的义务。为了更容易理解,规则实际上应该简化为要求
obj
的(静态)类型完全是S
。毕竟,子类D
出现在S
中是非常不寻常和不合适的。即使发生这种情况,obj
的静态类型是D
,我们的简化规则也可以通过向上转换轻松处理它:((S)obj)。会员
http://java.sun.com/docs/books/jls/third_edition/html/names.html#6.6
The motivation is probably as following. If
obj
is anS
, classS
has sufficient knowlege of its internals, it has the right to manipulate its members, and it can do this safely.If
obj
is not anS
, it's probably another subclassS2
ofC
, whichS
has no idea of.S2
may have not even been born whenS
is written. ForS
to manipulateS2
's protected internals is quite dangerous. If this is allowed, fromS2
's point of view, it doesn't know who will tamper with its protected internals and how, this makesS2
job very hard to reason about its own state.Now if
obj
isD
, andD extends S
, is it dangerous forS
to accessobj.member
? Not really. HowS
usesmember
is a shared knowlege ofS
and all its subclasses, includingD
.S
as the superclass has the right to define behaviors, andD
as the subclass has the obligation to accept and conform.For easier understanding, the rule should really be simplified to require
obj
's (static) type to be exactlyS
. After all, it's very unusual and inappropriate for subclassD
to appear inS
. And even if it happens, that the static type ofobj
isD
, our simplified rule can deal with it easily by upcasting:((S)obj).member
受保护的访问有一些特殊规则,详细信息请参见 Java语言规范:
Protected access has some special rules that are detailed in the Java Language Specification:
首先想到的是,您可以在任何软件中使用
protected
Object
,但只有不同的包非子类不能从其他类访问受保护的成员。这意味着你不能直接使用它。首先你得到那个 obj 然后使用。我们还有另一个类,就像
在这件事上你必须扩展受保护成员的类,然后使用你不能直接使用的。
First think is that you can use
protected
Object
in any ware, but only Different package non-subclass cant access protected member from other class. it means you cant use it directly. first you get that obj and then use.and we have another class like
in this matter you have to extends class of protected member and then use you cant use is directly.
它创建一个 Base 对象,然后尝试在其上调用 display()。
显然它不起作用,因为 Base 上的 display() 受到保护。
It creates a Base object, and then trys to call the display() on it.
Obviously it won't work, because the display() on Base is protected.
这是预期的行为。 protected 表示继承类和同包类都可以看到该方法。所以,这就是你所看到的。
This is the intended behaviour. protected means that the inherited classes and same package classes can see the method. So, it's what you see.