Why does a Java constructor have to be public or p

2020-06-18 03:16发布

问题:

The following is my ProtectedConstructor.java source code:

package protectCon;

public class ProtectedConstructor{
    public int nothing;
    ProtectedConstructor(){
        nothing = 0;
    }
}

And following is the UsingProtectedCon.java source:

package other;

import protectcon.ProtectedConstructor;

public class UsingProtectedCon extends ProtectedConstructor{   //**Line 4**
    public static void main(String... a) {  
    }
}

When I compile UsingProtectedCon.java, I get error at Line 4 shown above. It says that ProtectedConstructor() is not public ; so cannot be accessed outside package.

However, since my class is public, shouldn't I be able to extend it outside package. I am anyway not creating any instance of it.

Now, if I make the constructor of ProtectedConstructor class as public or protected then the code compiles fine with no error.

So then why is it necessary even for the constructor to be public or protected, and not just have default access?

回答1:

If you want to extends a class outside its package it must have a constructor that is public or protected because in Java every constructor must call a constructor from its superclass.

Because of this there is an implied super() call in every constructor which does not have this() or an explicit call to super() as its first statement. And if you don't specify a constructor at all Java will add a default parameterless constructor, so in effect your code looks like this:

public class UsingProtectedCon extends ProtectedConstructor {
    public UsingProtectedCon() {
        super();
    }

    public static void main(String... a) {   
    }
}

So in other words your code is failing to compile because the call to super() in the default constructor cannot be resolved.



回答2:

constructor is a member of class like field and method so access modifier applies to it in the same manner it apples to all the member of class

when you extend the class A in B , A's its default constructor will get called from B's constructor implicitly (if you don't call any of the overloaded constructor)



回答3:

in your class ProtectedConstructor is defined with Package-Private access This means that outside the package its not seen even by the classes that extend from your ProtectedConstructor class

Define your constructor with 'protected' access modifier instead and you'll be done:

 package protectCon;

public class ProtectedConstructor{
    public int nothing;
    protected ProtectedConstructor(){
        nothing = 0;
    }
}


回答4:

Your constructor is not public. Default scope is package-private.



回答5:

JLS 6.6.7 answers your question. A subclass only access a protected members of its parent class, if it involves implementation of its parent. Therefore , you can not instantiate a parent object in a child class, if parent constructor is protected and it is in different package.Since the default constructor of the subclass would try to call parent class constructor ,you got this error.

See this SO Post for details



回答6:

to avoid all confusion do it like this. package protectCon;

public class ProtectedConstructor{
    public int nothing;
    public ProtectedConstructor(){
        nothing = 0;
    }
}


package other;

import protectCon.ProtectedConstructor;
public class UsingProtectedCon extends ProtectedConstructor{   //**Line 4**

    public UsingProtectedCon(){
      super();
      }


  public static void main(String... a){   
    }
}


回答7:

You can have constructors which are public, protected (for internal used) and even private.

A simple example is String which has public constructors for general use and package-local constructors for internal use.

The ObjectOutputStream class has a public constructor which takes an OutputStream and a protected constructor which can only be used by a sub-class.

BTW: if you have an abstract class, does it make sense to make the constructor public as if often the case. ;) hint: it is the same as protected.



回答8:

If child will have constructor which is private in parent,we can make child's instance with that constructor and cast it to parent's type. So to prevent this java compiler is not allowing constructor to have constructor which is private in parent.