为什么在最终的java类中允许受保护的成员?
为什么在最终类中允许受保护的成员 这不应该是编译时错误吗为什么在最终的java类中允许受保护的成员?,java,oop,Java,Oop,为什么在最终类中允许受保护的成员 这不应该是编译时错误吗 编辑:正如人们指出的,您可以通过使用默认修改器获得相同的包访问权限。它应该以完全相同的方式运行,因为protected只是默认+子类,而final修饰符明确拒绝子类化,所以我认为答案不仅仅是提供相同的包访问。因为受保护的成员可以被同一包中的其他类访问,以及子类。受保护的修饰符还允许在同一个包中访问,而不仅仅是访问子类。因此,在最后一节课上,这并不是完全没有意义的。你可以这么说,但这并没有什么真正的伤害。一个非最终类也可能有一个受保护的成员
编辑:正如人们指出的,您可以通过使用默认修改器获得相同的包访问权限。它应该以完全相同的方式运行,因为protected只是默认+子类,而final修饰符明确拒绝子类化,所以我认为答案不仅仅是提供相同的包访问。因为受保护的成员可以被同一包中的其他类访问,以及子类。受保护的修饰符还允许在同一个包中访问,而不仅仅是访问子类。因此,在最后一节课上,这并不是完全没有意义的。你可以这么说,但这并没有什么真正的伤害。一个非最终类也可能有一个受保护的成员,但没有子类,它也不会打扰任何人。这里所说的
protected
成员可以被同一包的类访问的论点是有效的,但在这种情况下protected
变为等于默认可见性(包私有),问题依然存在——为什么两者都被允许
我想有两件事:
- 没有必要禁止它
- 在作出设计决定之前,可以暂时将一个类设置为最终类。每次添加或删除
final
方法而不向公众公开这些成员的方法,必须使用受保护的修饰符
一般来说,您可以引入许多不必要的规则来禁止不合理的组合(例如受保护的static
),但这不会有多大帮助。你不能宣布愚蠢为非法
package p;
import java.sql.Connection;
public final class ProtectedTest {
String currentUser;
Connection con = null;
protected Object ProtectedMethod(){
return new Object();
}
public ProtectedTest(){
}
public ProtectedTest(String currentUser){
this.currentUser = currentUser;
}
}
当然是这样,但是如果是这种情况,那么使用默认(包)访问会得到相同的结果,因此它仍然可能是一个编译错误。我认为这只是更多的证据,证明他们应该保持子类可见性和包/内部类可见性作为完全独立的概念。他们是谁告诉我,如果子类具有可见性,那么包也必须具有可见性?@Mark:是的,这显然没有经过深思熟虑。“受保护的成员可以被同一包中的其他类访问”:真的吗?!我还以为那就是私人包裹的用途呢?@Coronatus,请参阅JLS 6.6.1@Mark Peters、agreed和package access不应是默认值。@Coronatus:是的。但是,也受到保护
。这个问题的一个变体仍然有效:为什么我们可以有私有的静态final方法?“私有”意味着“最终”和“静态”,对吗?这难道不是多余的吗?@gawi:我不知道如何解释你的评论,但是private
当然并不意味着static
/final
@gawi:private意味着非虚拟的,而不是静态的,说“private意味着final”是没有意义的,因为“final”只对继承的方法有意义。我同意,因为我找不到在私有方法声明中使用“final”的有效理由。您也可以在抽象类中使用公共构造函数,这是一种常用的模式。仅仅因为它不是很有用,并不意味着它是一个错误。在方法上,“static”与final/non-final方面不兼容,因为静态方法不能被重写。在基类B中拥有最终的静态方法x()不会阻止派生类D拥有自己的x()方法。静态方法的最后一个关键字没有任何意义。+1:然而,我很惊讶“不正确”的答案这么快就被选中了。它能说明一般知识吗?啊,好的。因为您不能降低可见性以使它们成为默认或私有(这可能是最终类中的目的),所以您可以将它们保留为受保护或公开。虽然在这种情况下,将它们设为默认值并不会降低可见性(因为不可能进行子类化),但是编译器应该停止抱怨。是的。我应该说你可以把它们公开,但你不想。实际上,如果在另一个包中重写,则受保护的
的行为会特别明显。我不喜欢受保护的。行为特别如何?你的意思是说受保护的会有包访问是不直观的吗?@orbbish如果你有一个具有受保护方法的类,那么同一个包中的类可以访问它。到目前为止还不错(很糟糕,但你知道)。现在考虑一个派生类,该类重写该方法,使之受到保护。现在,原始包中的类不能访问它,除非它们将对象分配给基类类型的变量。这“打破了LSP”而且很难看。但是避开保护,你就看不见了。@Tom-我甚至没想到,谢谢!现在,如果我能弄清楚为什么有人会在最终的非子类中有一个受保护的成员……那些被证明是无用的东西是编译错误的好候选(警告会更好),而不是因为它们直接“打扰”或“伤害”任何人/事,而是因为它很有可能是程序员的错误/打字错误。你怎么能证明它是无用的?将最终类更改为非最终类甚至不会破坏二进制兼容性。
package p;
public class CallProtectedTest {
public void CallProtectedTestMethod() {
System.out.println("CallProtectedTestMethod called :::::::::::::::::");
ProtectedTest p = new ProtectedTest();
Object obj = p.ProtectedMethod();
System.out.println("obj >>>>>>>>>>>>>>>>>>>>>>>"+obj);
}
}
package p1;
import p.CallProtectedTest;
public class CallProtectedTestFromp2 {
public void CallProtectedTestFromp2Method(){
CallProtectedTest cpt = new CallProtectedTest();
cpt.CallProtectedTestMethod();
}
public static void main(String[] args) {
CallProtectedTestFromp2 cptf2 = new CallProtectedTestFromp2();
cptf2.CallProtectedTestFromp2Method();
}
}