I have three classes like this:
public abstract class ClassA extends ClassX {
protected ClassA() {
super();
}
// more code
}
public class ClassB extends ClassA {
public ClassB() {
super();
}
// more code
}
public abstract class ClassC extends ClassB {
public ClassC() {
super();
}
// more code
}
I would say that the standard constructor for ClassC is not necessary since Java will insert it during compilation, since there is no other constructor in this class, right?
If true, I could simplify the code for ClassC down to this:
public abstract class ClassC extends ClassB {
// more code
}
Now I'd say that I can't do the same for ClassB since the accessibility of the constructor is increased from protected to public.
I'm asking since I am not 100% sure about this and thought I might be missing something. Especially about the standard constructor that will be inserted into ClassC if I don't implement it myself. In this case it will have accessibility public since it inherits from ClassB. Is that correct?
So my question is: Can I delete the constructor in ClassC without having the code being changed (especially the accessibility of constructors) and is it correct that I can't delete the constructor of ClassB.
Now I'd say that I can't do the same for ClassB since the accessibility of the constructor is increased from protected to public.
That's irrelevant, given that it's an abstract class. The constructor can't be called directly - it's only used when chaining from a subclass constructor.
So while it would be technically different, your code would be effectively the same if you removed all the constructor declarations.
But in terms of the accessibility of default constructors, JLS 8.8.9 is the authority here:
If a class contains no constructor declarations, then a default constructor is implicitly declared. The form of the default constructor for a top level class, member class, or local class is as follows:
The default constructor has the same accessibility as the class (§6.6).
...
The rule that the default constructor of a class has the same access modifier as the class itself is simple and intuitive. Note, however, that this does not imply that the constructor is accessible whenever the class is accessible.
If you do not make a constructor, the default empty constructor is automatically created.
If any constructor does not explicitly call a super or this constructor as its first statement, a call to super() is automatically added.
That means if your constructors are defined with in the scope of the child class then there is no need to call super() explicitly. As in your case you can remove all the constructors. Your program will still compile and run.
Hope this helps. For more please have a look at the shared links, it has some more beautiful examples.
From the Java specification on default constructor.
If a class contains no constructor declarations, then a default constructor with no formal parameters and no throws clause is implicitly declared.
If the class being declared is the primordial class Object, then the default constructor has an empty body. Otherwise, the default constructor simply invokes the superclass constructor with no arguments.
So you should be good with not including any of those constuctors.
Related
I have seen a lot of code that doesn't refer to any constructors. I have created code that doesn't contain constructors which seemingly defies the point of having one. Are there rules for when one needs to implement a constructor?
You don't have to provide any constructors for your class, but you
must be careful when doing this. The compiler automatically provides a
no-argument, default constructor for any class without constructors.
This default constructor will call the no-argument constructor of the
superclass. In this situation, the compiler will complain if the
superclass doesn't have a no-argument constructor so you must verify
that it does. If your class has no explicit superclass, then it has an
implicit superclass of Object, which does have a no-argument
constructor.
As provided by the javaOO documentation
If you have a class "A", and you don't create a constructor, a constructor:
public A(){
}
will be implicitly created, i.e. you won't actually see it. (thanks, #Steve Smith)
If you create any constructor, this default constructor will not be created. This is important when using certain design patterns like factory method and singleton.
If you create a private constructor:
private A(){
}
the default constructor (that is public) will not be created. This means that only inside the class A you can create instances of A. To export instances of A to other classes, you need to create them on static methods and return the references. This is employed on the Singleton pattern, for instance:
public A{
private static A instance = new A();
public static A getInstance(){
return instance;
}
//the default public constructor will not be created
private A(){
}
}
To answer your question, you HAVE to provide a constructor if you want to ensure that the instantiated object is initialised with certain data. For example, you might want to have a Person class which always has a valid first & last name as well as an age.
Person hugo = new Person("Hugo", "First", 25);
the constructor would then be
public Person(String first, String last, int age) {
setFirst(first);
setLast(last);
setAge(age);
}
protected Person() {}
This way it is impossible to instantiate an empty Person.
This question already has answers here:
What is the actual use of the default constructor in java?
(7 answers)
Closed 4 years ago.
There is something that I don't understand about the real role of the default constructor in java. In the official tutorial about object creation :
Creating Objects
All classes have at least one constructor. If a class does not explicitly declare any, the Java compiler automatically provides a no-argument constructor, called the default constructor. This default constructor calls the class parent's no-argument constructor, or the Object constructor if the class has no other parent. If the parent has no constructor (Object does have one), the compiler will reject the program.
And in the docs about the Default Constructor (§8.8.9)
8.8.9. Default Constructor
If the class being declared is the primordial class Object, then the default constructor has an empty body. Otherwise, the default constructor simply invokes the superclass constructor with no arguments.
So even the default constructor of the class Object has an empty body. And I know that the default constructor does NOT initialize fields to their default values, because it's the compiler who does that :
Default Values
It's not always necessary to assign a value when a field is declared. Fields that are declared but not initialized will be set to a reasonable default by the compiler.
What I don't understand is, if we didn't declare a constructor, what does the default constructor really do ?
what does the default constructor really do?
It calls super(). As per all your quotations. And does nothing else. JLS #8.8.9:
If the class being declared is the primordial class Object, then the default constructor has an empty body. Otherwise, the default constructor simply invokes the superclass constructor with no arguments.
i.e. it does nothing else. For those who believe it initializes instance variables please see JLS #12.5 where the contrary is asserted.
In Java, if you don´t declare any constructor the compiler create a default constructor and this constructor call to super() method, that is parents constructor. And in this process, inits instance variables like no-default constructors.
What I don't understand is, if we didn't declare a constructor, what
does the default constructor really do ?
By default, if no constructor is declared, a class has a default constructor with no args. I think that's why, by default all constructor calls super(). It follows probably the convention over configuration principle.
Whatever you declare a public constructor or you don't declare at all constructor, first instruction of the constructor is super().
That's why if you define in a class MyClass a constructor with args MyClass(String s) without keeping a constructor with no argument, constructor of MyClass subclasses cannot compile while it doesn't precise in their first instruction, the call to an existing parent constructor, in the exemple, it would be super(String ...).
Here an example :
public class MyClassWithNoArg{
public MyClassWithNoArg(){
}
}
MyClassWithNoArg constructor calls super() in this first instruction even if it not specified in the source code.
It is as if it is written in this way :
public class MyClassWithNoArg{
public MyClassWithNoArg(){
super();
}
}
Imagine now another class MyClassWithArg:
public class MyClassWithArg{
public MyClassWithNoArg(String s){
}
}
And MySubclass a subclass of MyClassWithArg
public class MySubclass extends MyClassWithArg{
public MySubclass (String s){
}
public MySubclass (){
}
}
In both cases, it will not compile since as explained previously all constructors call by default the default constructor (super()) of their parent but here the parent,MyClassWithArg, has no constructor with no arg. So, it doesn't compile.
So to solve the problem, you have to call the super constructor which exists.
public class MySubclass extends MyClassWithArg{
public MySubclass (String s){
super(s);
}
public MySubclass (){
super("");
}
}
Now, compilation is OK.
Without constructor no one can create a object of a class. Now if programmer does not add any constructor with a class then java compiler added a constructor with that class before compilation,which is known as default constructor in java.
But if programmer adds any kind of constructor(with argument or without argument) then that becomes user defined constructor and no constructor 'll be added via java compiler.
Now question is what does constructor do.
allocates memory for new object
if user defines any other operation like initialising variable that is done.
If I create an object of a sub-class with no constructors, then I know that the compiler will implicitly provide a default constructor. What if I create a constructor in the sub-class and try to access the super class constructor using the super keyword, and, now, the super class has no constructor in it. Will the compiler provide a default constructor for the super class as well?
Yes, if there is no specified constructor, there is always default empty constructor
Does the compiler provides a default constructor for the super class also???
The default constructor will be there whether or not there is a subclass that needs it. The default is supplied when the parent is compiled, not later.
...What if I created sub class Constructor and trying to access the super class constructor using the super keyword,and the super class has no constructor in it.
But it does: The default one.
It goes like this.
Lets speak about Object which is the supermost class in java, If you open an editor and just make a class, then it is presumed that It is extending Object. Every class in Java extends from Object. If you do not write your own constructor then Compiler will provide one.
But if you write your own constructor let's say a constructor with one argument, compiler will not provide you with any constructor.
Now lets say taht you extend the above class, then compiler will complain you saying that the superclass does not have a default constructor rather a custom constructor so you need to make one constructor for this child class since first constructor which is called starts from the supermost class that is OBJECT and then proceeds down the line.
Hope this answers comprehensively,
Thanks.
Yes the super always occurs even if you didnt explicit declare
public class FatherTest {
}
public class SonTest extends FatherTest{
public SonTest(String sonName){
super(); // this will always occurs
}
}
If you don't write a constructor for a class, the compiler will implicitly add an empty one for you.
That means this:
public class X {
}
is identical to this:
public class X {
public X() {
// there's also an implicit super(); added here, but that's not directly relevant
}
}
If the super class doesn't have explicit constructor, then an implicit default constructor will be added to it. So your super() will invoke that.
If the super class only have some constructors with parameters. Then super() in the sub-class won't compile. You have to explicitly use one of the defined super-class constructor super(param1, param2, ...), since super() will be called if you don't call it.
As per Joshu Bloch's Effective Java,"The main disadvantage of providing only static factory methods is that classes without public or protected constructors cannot be subclassed." Can someone please explain what does this mean? Especially the bolded words. If a static factory method is provided or not, class with private constructor can't be subclassed right?
Providing only static factory methods is that classes without public
or protected constructors cannot be subclassed.
Whenever a constructor of a subclass is called, the constructor of the parent class is also called. In the absence of protected or public constructors, sub classing or extending a class will make no sense. Hence the disadvantage.
Java requires from derived class to ensure that inherited fields will be properly initialized. It is done by making at start of constructor call to constructor of superclass.
Such code should look like
class Derived class Parent{
public Derived(){
super();//this will be added automatically by compiler
//or super(arguments) if you want to use constructor with arguments
}
}
But if superclass doesn't make its constructor accessible (it is privet) derived class can't add super call in any of its constructor. This means that we can't create valid code for constructor, and since all classes must have at least one constructors derived class can't compile.
I saw this question in one of my question papers:
Why should the derived class constructor always access base class constructor?
I'm wondering whether the question is valid?
So that you may have a valid object of type "Base" before you start messing with the inherited functionality in your derived object!
It's not valid. There's no 'should' about it: it must, and the compiler enforces it, by calling the base class's default constructor if it exists, and giving you a compile error if it doesn't, which forces you to call one of the existing constructors.
There is one exception to always, a default constructor in a superclass isn't usually called explicit.
If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass. If the super class does not have a no-argument constructor, you will get a compile-time error. Object does have such a constructor, so if Object is the only superclass, there is no problem.
Because the base class may do work you are not aware of.
Because the base class may have members that require initialization.
Since the derived class constructor wants to inherits from the base class constructor, it is necessary to call the base class constructor. Otherwise, if you don't, you will not inherit values initialised in base class constructor.
Calling a superclass constructor is not a must but a should paired with a strong advise - as long as the superclass has a default constructor. Otherwise the compiler forces you to call at least one of the superclasses constructors.
If the default constructor is present, it's called anyway, even without an explicit super() statement in the subclasses construtor.
A visible part of class construction is the initialization of fields. But there's more under the hood (memory allocation, registration, etc). All this has to be done for all superclasses when a derived class is created.
You do not need to call constructor when there is a default constructor (i.e a no-argument constructor) present in the base class. When there is a constructor with arguments present and no default constructor, then you don't need to declare a constructor in the child class.
You only need to initialize the child class constructor when there is no default constructor present in the parent class.
Example :
class A {
public int aInstanceVariable;
public A(int aInstanceVariable) {
this.aInstanceVariable = aInstanceVariable;
}
}
class B extends A {
// In this case we have to call super in base class constructor
}
However, when public A() {} is present in class A, there is no need to initialize the child class constructor.