受保护的程序包和私有程序(无修饰符)构造函数之间的区别?

时间:2018-09-17 07:04:45

标签: java

Possible Duplicate

给出的最高答案指出,可以使用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();
    }
}

3 个答案:

答案 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(),那么您已经有一个实例,因此,如果您在子类中并调用受保护的构造函数,它将起作用。