给出的最高答案指出,可以使用super()
调用受保护的构造函数,但是不能使用new
实例化该保护的构造函数吗?为什么这样?如果那是原因,那么package-private(no修饰符)和受保护的构造函数之间有什么区别?
以下代码并没有给我带来任何不同。
package pack1;
public class Rr {
protected Rr() {
System.out.println("Rello");
}
}
package pack2;
class Tt extends pack1.Rr {
Tt() {
super(); //works
pack1.Rr r = new pack1.Rr(); //error
}
}
class Uu {
public static void main(String args[]) {
Tt t = new Tt();
}
}
答案 0 :(得分:1)
“默认构造函数”是Java生成的构造函数,如果您自己不提供的话;它始终具有与类本身相同的访问权限,并且没有参数。也就是说,当您定义
class YourClass {}
系统成功
class YourClass {
YourClass() {} // default constructor
}
如果您创建其他任何构造函数-甚至是一个没有参数的public
,它也是默认构造函数 not 。上面的第二段代码将阻止系统生成一个,因为您已经声明了它。
如果创建protected
构造函数,则同样如此。比较:
public class Class1 {}
public class Class2 {
protected Class2() {}
}
您可以实例化Class1,但不能实例化Class2:
// invokes autogenerated default constructor
Class1 c1 = new Class1();
// compile error: default constructor is not generated because you declared a protected one
Class2 c2 = new Class2();
正如@ Turing85在评论中所述,protected
修饰符仅意味着声明的构造函数只能在正确的访问范围内调用-从同一包中的子类或类。
出于完整性考虑:您可以从子类中显式调用super()
和构造函数:
class Class3 extends Class2() {
public Class3() {
// call to protected constructor of Class2
super();
// explicit call to constructor by creating new instance
Class2 o = new Class2();
}
}
编辑:我刚刚尝试过,最后一个示例仅在两个类位于同一包中时才有效。我不知道,也想知道。
答案 1 :(得分:1)
可以通过其子类对象访问protected
方法。
请注意,这里的“子类”非常重要,这意味着“通过子类方式”,而不是“子类中的任何位置”。
我们来看一个例子。
以下是2类:
package one;
public class A {
protected A() {} // protected constructor
public A(int i) {} // public constructor
protected void foo() {} // protected method
}
package two;
import one.A;
public class B extends A {
public void bar() {
this.foo(); // correct
A a = new A(0); // call A's public constructor to construct an A instance.
a.foo(); // compiler error: the method foo from the type A is not visible.
}
}
允许第一次调用,但是第二次不允许,为什么?
就像我说的那样,第一个是通过“子类方式”访问的,其中this
是A的子类实例;但是第二个只是“在子类中”(这里B对A而言没有意义,它只是一个普通类,因此它无法访问A的受保护方法)。
另一个示例是Object.clone
。这是根类Object
的受保护方法。您可能会说可以从任何类创建的任何对象中访问它,但答案是大写的“否”:只有那些使用“子类方式”的代码才能访问它。
以下说明了这一点:
this.clone(); // ok
Object o = new Object();
o.clone(); // compiler error: the method clone from the type Object is not visible.
答案 2 :(得分:0)
protected
还提供对子类的访问。
当您直接调用构造函数时,例如new A()
可以认为它是调用 static 方法。该类尚无实例,因此继承规则不适用。因此,适用静态访问规则:如果构造函数受到保护,则它必须位于同一包中才能访问。
一旦您进入构造函数代码并调用super()
,那么您已经有一个实例,因此,如果您在子类中并调用受保护的构造函数,它将起作用。