Karla Carr
Karla Carr

Reputation: 21

Difference between a protected and package-private (no modifier) constructor?

Possible Duplicate

The top answer given there states that the protected constructor can be called using super() but cannot be instantiated using new? Why so? And if that is the reason then what is the difference between package-private(no modifier) and protected constructor? The following code is not getting me any difference.

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();
    }
}

Upvotes: 2

Views: 1318

Answers (3)

daniu
daniu

Reputation: 14999

A "default constructor" is a constructor that Java generates if you don't provide one yourself; it's always has the same access as the class itself and has no arguments. Ie when you define

class YourClass {}

the system makes it

class YourClass {
    YourClass() {} // default constructor
}

If you create a any other constructor - even a public one with no arguments - it is not a default constructor. The second code piece above would prevent the system from generating one, because you already declared it.

The same is true if you create a protected constructor. Compare:

public class Class1 {}

public class Class2 {
    protected Class2() {}
}

you can instantiate Class1, but not 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();

As @Turing85 states in a comment, the protected modifier only means that the declared constructor can only be invoked within the proper access scope - from subclasses or classes in the same package.

For completeness' sake: you can call both super() and the constructor explicitly from a subclass:

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(); 
    }
}

EDIT: I just tried it out, and the last sample is only valid if the two classes are in the same package. I don't know and would like to know.

Upvotes: 1

terry.qiao
terry.qiao

Reputation: 2045

A protected method can be accessed via its sub-class objects.

Note, "sub-class" here is very important, which means "via a sub-class way", not "anywhere within a sub-class".

Let's look at an example.

Following are 2 classes:

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.
    }
}

The first invocation is permitted, but the second not, why?

Like I said, the first one is accessing via "a sub-class way", in which this is A's sub-class instance; however the second just "within a sub-class" (here B is no meaning to A, it's just an ordinary class, so it can not access A's protected method).


Another example is Object.clone. This is a protected method of root class Object. You might likely say it can be accessed from any object created from any class, but the answer is capital "NO": only those codes which are using "sub-classes way" can access it.

The following illustrates this:

this.clone(); // ok

Object o = new Object();
o.clone(); // compiler error: the method clone from the type Object is not visible.

Upvotes: 1

memo
memo

Reputation: 1938

protected gives access to subclasses, in addition to the classes in the same package. When you call the constructor directly, e.g. new A() you can think of it as calling a static method. There is no instance of the class yet, thus inheritance rules cannot apply. Therefore, static access rules apply: if the constructor is protected, then it must be in the same package in order to be accessible.

Once you are inside a constructor code and you call super(), then you already have an instance, so if you are in a subclass and call the protected constructor it will work.

Upvotes: 0

Related Questions