Why is my subclass constructor not called? - java

I have this inheritance structure:
public abstract class Mom {
int dummy;
Mom() {
dummy = 0;
}
Mom(int d) {
this();
dummy = d;
}
}
public class Kid extends Mom {
String foo;
Kid() {
super();
foo = "";
}
Kid(int d) {
super(d);
}
}
// ...
Kid kiddo = new Kid(10);
// kiddo.foo == null !
My argument-less constructor of Kid is never called! Here's what I expected:
new Kid(10) → Kid#Kid(int)
super(d) → Mom#Mom(int)
this() → Kid#Kid() // doh!!
super() → Mom#Mom()
Is it possible, from Mom, to call Kid's argument-less constructor?
I guess it's not, and I'll add an abstract method[1] init() that Mom will call and that Kids will have to override.
But I just wanted to know the exact reason, and if possible, examples proving why wanting to call subclass' constructor is a bad idea (even if the subclass' constructor does call super()).
// in Mom:
protected abstract void init();
public Mom() {
dummy = 0;
init();
}
// in Kid:
#Override
protected abstract void init() {
foo = "";
}

The way I would arrange these so you don't need to call every constructor.
public abstract class Parent {
final int dummy;
Parent () {
this(0);
}
Parent (int d) {
dummy = d;
}
}
public class Kid extends Parent {
final String foo = "";
Kid() {
}
Kid(int d) {
super(d);
}
}
Using final ensures that every fields is set once.
Its considered bad practice to call any override-able method from a constructor, so making constructors override-able which be a bad idea.
this() calls the constructor of the same class because constructors don't follow inheritance (nor do static methods)
new Kid(10) --> Kid#Kid(int)
super(d) --> Mom#Mom(int)
this() --> Mom#Mom()
Constructors do this otherwise you are in danger for calling the same constructor more than once and there is no way to guarantee that final methods are set only once.

From the JLS §8.8.7.1 (emphasis by me):
Alternate constructor invocations begin with the keyword this (possibly prefaced with explicit type arguments). They are used to
invoke an alternate constructor of the same class.
Superclass constructor invocations begin with either the keyword super (possibly prefaced with explicit type arguments) or a Primary
expression. They are used to invoke a constructor of the direct
superclass.
So, a this-constructor-invocation always refers to the same class, never to a child class.
While it is possible to invoke virtual methods in a constructor, it is unsafe and considered bad practice as it may result in those methods working with partly initialized object instances.
For your problem, there are several possible solutions:
Initialize the member foo at declaration, i.e. foo = "";. This is also known as field initializers
Use an instance initializer: { foo = ""; }. Note that you can have more than one instance initializer if needed in your class.
Bite the bullet and repeat the initialization in all constructors
According to JLS §12.5, initialization in (1) and (2) is always executed before constructors themselves are called, so you have a well-defined object initialization without the need of resorting to problematic patterns.
If a member is initialized multiple times, then the last initialization wins:
4) Execute the instance initializers and instance variable initializers
for this class, assigning the values of instance variable initializers
to the corresponding instance variables, in the left-to-right order in
which they appear textually in the source code for the class.
If the same field is initialized in a constructor as well, then the constructor wins.

You should have these constructors for the Kid class:
Kid(int i) {
super(i);
whatever();
}
Kid () {
this( DEFAULT_VALUE);
}
so that all call to parent constructor are made via fully qualified constructor of child class. And have a default behavior for all constructor of your class that is not bypassed as it is the case with your current code.

Related

Just like superclass members, do superclass constructors form part of the subclass object state?

Please allow me to explain my understanding.
class P
{
P()
{
System.out.println("hi "+this);
/*which object of P is currently executing this constructor?
Is "this" here object referenced by q or some other object?*/
}
}
class Q extends P
{
Q()
{
super();
/*constructor of superclass called on this object(referenced by q) */
}
}
class R
{
public static void main(String args[])
{
Q q = new Q(); //constructor Q() invoked on object referenced by q
}
}
So my doubts are:
1. super() is invoked on which object of P(since none exists).
2. What is "this" in P() referring to? Is it the same object as q? In other words is this=q ?
Code, ctors included, does not define 'object state'. Set of instance fields do. And, under the hood, subclass instances do include private fields of their superclasses, but javac makes sure that they only accessible, directly or indirectly, by calling superclass methods (ctors included).
Regarding your updated question:
class Q extends P
{
Q()
{
super(); /*constructor of superclass called on this object(referenced by q) */
}
}
Here Q extends P, so super() calls P's ctor. During execution of P's ctor, this allows to refer to fields and methods belonging to P and to it's supertypes (e.g., Object) w/ restrictions imposed by access modifiers (I mean you can access only public and, w/ restrictions protected and 'package-private' members of subtypes), but not to P's subtypes.
Regarding "no access to P's subtypes" rule there's one more twist: if you call some non-private (overridable) method of P from P's ctor, chances are this method will be overridden someday in Q or other subtype, and you suddenly start calling some unforeseen code! So, this inside P does allow to refer explicitly to P's subtype methods but not to P's subtype fields (although implicitly P's fields can be reached by P's subtype method).
To give an example -- change f() in following code from private to 'package-local' and witness a NPE thanks to following execution chain Derived#Derived() -> Base#Base() -> Derived#f() -> NPE!:
class Base {
private Integer base = 1;
Base() {
f();
}
private void f() {
System.out.println(base);
}
}
class Derived extends Base {
private Integer derived;
Derived() {
super();
derived = 2;
f();
}
private void f() {
System.out.println(derived.intValue());
}
}
Constructors are not inherited to subclasses. And using super() you can just call the super class constructor. You can not access the private variable/property of super class from subclass. Moreover private member of a super class is also not inherited to it's subclass.
Constructors are not inherited in java.
As per the official Java tutorial:
A subclass inherits all the members (fields, methods, and nested
classes) from its superclass. Constructors are not members, so they
are not inherited by subclasses, but the constructor of the superclass
can be invoked from the subclass.
When you call super() you simply invoke the parent constructor, which can access private members of the class it belongs to.
As for the updated version of your question:
As mentioned above, super() simply invokes the parent constructor. It's not invoked on any object, since constructor is not a member of a class.
this in the P constructor will refer to the instance of a subclass (Q) that is being constructed.
EDIT:
Regarding 2. This can be easily verified by outputting the reference q in your main method. It should print exactly the same that the System.out.println(this) call in the P constructor.
public class R
{
public static void main(String args[])
{
Q q = new Q(); //constructor Q() invoked on object referenced by q
System.out.println(q);
}
}

How is this subclass implicitly calling the constructor of its parent class?

I have these two classes:
public class Document {
private static int quantity = 0;
public Document() {
quantity = quantity + 1;
}
public static int getQuantity() {
return quantity;
}
}
public class Book extends Document {
private int numChapters;
public Book(int numChapters) {
this.numChapters = numChapters;
}
public static void main(String[] args) {
Book b1 = new Book(4);
Book b2 = new Book(6);
Document d1 = new Document();
System.out.println(Document.getQuantity());
}
}
The program here returns 3, but I expect it to return 1. Can someone tell me what is happening in the code? It seems that the parent class's constructor is being implicitly called when b1 and b2 are created. From what I understand, subclasses don't inherit the constructor of their parent class.
See the docs:
Note: 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.
You have a no-argument constructor which is automatically called.
This behavior makes sense, constructors are meant to create objects. So it should contain proper initialization code for its class. What if you your class extends another one? Shouldn't it contain all the code needed to construct that object?
sub-classes must call a constructor of their super class, even if the sub-class's constructors don't explicitly call super(). In fact, if the compiler can't find a super-class's constructor that it can call from the sub-class's constructor, the code won't compile.
It seems that the parent class's constructor is being implicitly called when b1 and b2 are created.
That is correct.
From what I understand, subclasses don't inherit the constructor of their parent class.
That is also correct. However, it does NOT mean that the superclass constructor is not called.
In Java, when an object is created1 using new (or the reflective equivalent) a superclass constructor is always called, whether or not you have a super(...) call in the subclass constructor.
1 - For the record, when an instance is created by object deserialization, no constructors are called. The recreation of the object is done by some behind-the-curtains black magic that makes the object without calling its constructor.

Can a java subclass's private final field be initialized before the super constructor completes?

I have a pair of classes looking like this;
public abstract class Class1 {
//...
public Class1() {
//...
function2();
//...
}
protected abstract void function2();
}
public class Class2 implements Class1 {
private final OnSomethingListener mOnSomethingListener = new OnSomethingListener() {
#Override
onSomething() {
doThatOtherThing();
}
}
protected void function2() {
//uses mOnSomethingListener
//however mOnSomethingListener is null when this function is called from super()
//...
}
public Class2() {
super();
}
}
I assume the listener is null because I am effectively referencing it from super() and it hasn't instantiated yet. However, I want to make it final because, well, it is. Can I get this field (the listener) to initialize in time without putting it in the superclass (which won't be using the listener, ever)?
Your design is an instance of the "leaked this problem" and is an anti-pattern in Java. You should never call out to a publicly overridable method from a constructor.
Short answer - no. A superclass' constructor, field initialisers and instance initialisers are always called before the subclass'.
The order of calls is formally defined in section 8.8.7.1 of the JLS. Summarising the relevant last parts (where S is the superclass and C is the subclass):
After determining the immediately enclosing instance of i with respect to S (if any), evaluation of the superclass constructor invocation statement proceeds by evaluating the arguments to the constructor, left-to-right, as in an ordinary method invocation; and then invoking the constructor.
Finally, if the superclass constructor invocation statement completes normally, then all instance variable initializers of C and all instance initializers of C are executed. If an instance initializer or instance variable initializer I textually precedes another instance initializer or instance variable initializer J, then I is executed before J.
So when the superclass constructor runs, the subclass and all its fields are completely uninitialised. It's bad practice to call overridden methods from a constructor for this reason. You're essentially letting a reference to the object "escape" from its constructor, which means all the guarantees of construction are off (including things like final fields changing value, etc.).
Calling an abstract method from a constructor is almost always the wrong thing to do. Depending on the implementation of the method in the subclass(es) you might get away with it in some case (i.e. if the method does not depend on any state at all), but it will almost certainly cause a hard-to-debug failure at some point.
For example, would you expect there to be a difference between:
protected String function2() {
return "foo";
}
and
private final String foo = "foo";
protected String function2() {
return foo;
}
Analysing problems like this is hard, because they break the mental model of how classes work. Best to avoid this situation altogether.
super classes are always initialised before subclasses. Only static fields of a sub class can be initialised first.
You can call an overridden method from the super class which then accesses a field which is not initialised. This is considered bad practice.

Java Constructor and Field Initialization Order

I aware that Java object constructors implicitly initialize their instance's non-static fields. However, I'm unsure of the order that this happens in a class hierarchy. For example:
abstract public class AbstractPieceSequence implements PieceSequence
{
private Tetromino current;
private Tetromino preview;
public AbstractPieceSequence()
{
advance();
}
#Override
public final void advance()
{
if (preview == null) {
current = getNextPiece();
preview = getNextPiece();
} else {
current = preview;
preview = getNextPiece();
}
}
abstract protected Tetromino getNextPiece();
}
public class ShufflePieceSequence extends AbstractPieceSequence
{
private List<Shape> bag = new LinkedList<Shape>();
#Override
protected Tetromino getNextPiece()
{
if (bag.size() == 0) {
Collections.addAll(bag, Shape.I, Shape.J, Shape.L, Shape.O, Shape.S, Shape.T, Shape.Z);
}
return Tetromino.tetrominoes.get(bag.remove(0));
}
}
The parent's constructor calls a method in the child class, which throws an exception as the value of List<Shape> bag is currently null.
I can define a child constructor and call super(), but that must be the first line in the constructor body (which means I still don't have a chance to initialize bag before getNextPiece is called).
I am missing something obvious.
That's right. super(), even if you don't add it explicitly, is placed implictly in every constructor. This means that the constructor of ShufflePieceSequence is called first, but the very first thing it does is calling AbstractPieceSequence.
In AbstractPieceSequence you are calling a method defined in ShufflePieceSequence - which has not been initialized. In fact what you are doing is actually a very subtle bug. You should never call overridable (including abstract methods) from constructor. Period. AFAIR tools like pmd and findbugs are marking this as a potential bug.
See also
What's wrong with overridable method calls in constructors?
Use Care When Calling Non-final Methods from Constructors
Ensure that constructors do not call overridable methods
Object fields are not implicitly initialized... you need to do the init. Maybe you need a lazy init in this case? Generally unpleasant to have the constructor calling methods that do non-trivial work, it's usually a smell that something is more complex than it wants to be.
Depth first, a pre-order walk.
Anders makes a good point: Java only initializes fields that are native types implicitly. Any Object field is merely a reference to Object, and so it in fact initialized, but it's initialized to null.
The order of invoking the constructors of Parent-Sub class in case of inheritance is that, the constructor of Parent class always gets invoke first and then the constructor of Child class.
The Sub class calls the constructor of the base class by default using the Super(), if explicitly not given.

Difference between "this" and"super" keywords in Java

What is the difference between the keywords this and super?
Both are used to access constructors of class right? Can any of you explain?
Lets consider this situation
class Animal {
void eat() {
System.out.println("animal : eat");
}
}
class Dog extends Animal {
void eat() {
System.out.println("dog : eat");
}
void anotherEat() {
super.eat();
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
Dog d = new Dog();
d.eat();
d.anotherEat();
}
}
The output is going to be
animal : eat
dog : eat
animal : eat
The third line is printing "animal:eat" because we are calling super.eat(). If we called this.eat(), it would have printed as "dog:eat".
super is used to access methods of the base class while this is used to access methods of the current class.
Extending the notion, if you write super(), it refers to constructor of the base class, and if you write this(), it refers to the constructor of the very class where you are writing this code.
this is a reference to the object typed as the current class, and super is a reference to the object typed as its parent class.
In the constructor, this() calls a constructor defined in the current class. super() calls a constructor defined in the parent class. The constructor may be defined in any parent class, but it will refer to the one overridden closest to the current class. Calls to other constructors in this way may only be done as the first line in a constructor.
Calling methods works the same way. Calling this.method() calls a method defined in the current class where super.method() will call the same method as defined in the parent class.
From your question, I take it that you are really asking about the use of this and super in constructor chaining; e.g.
public class A extends B {
public A(...) {
this(...);
...
}
}
versus
public class A extends B {
public A(...) {
super(...);
...
}
}
The difference is simple:
The this form chains to a constructor in the current class; i.e. in the A class.
The super form chains to a constructor in the immediate superclass; i.e. in the B class.
this refers to a reference of the current class.
super refers to the parent of the current class (which called the super keyword).
By doing this, it allows you to access methods/attributes of the current class (including its own private methods/attributes).
super allows you to access public/protected method/attributes of parent(base) class. You cannot see the parent's private method/attributes.
super() & this()
super() - to call parent class constructor.
this() - to call same class constructor.
NOTE:
We can use super() and this() only in constructor not anywhere else, any
attempt to do so will lead to compile-time error.
We have to keep either super() or this() as the first line of the
constructor but NOT both simultaneously.
super & this keyword
super - to call parent class members(variables and methods).
this - to call same class members(variables and methods).
NOTE: We can use both of them anywhere in a class except static areas(static block or method), any
attempt to do so will lead to compile-time error.
this is used to access the methods and fields of the current object. For this reason, it has no meaning in static methods, for example.
super allows access to non-private methods and fields in the super-class, and to access constructors from within the class' constructors only.
When writing code you generally don't want to repeat yourself. If you have an class that can be constructed with various numbers of parameters a common solution to avoid repeating yourself is to simply call another constructor with defaults in the missing arguments. There is only one annoying restriction to this - it must be the first line of the declared constructor. Example:
MyClass()
{
this(default1, default2);
}
MyClass(arg1, arg2)
{
validate arguments, etc...
note that your validation logic is only written once now
}
As for the super() constructor, again unlike super.method() access it must be the first line of your constructor. After that it is very much like the this() constructors, DRY (Don't Repeat Yourself), if the class you extend has a constructor that does some of what you want then use it and then continue with constructing your object, example:
YourClass extends MyClass
{
YourClass(arg1, arg2, arg3)
{
super(arg1, arg2) // calls MyClass(arg1, arg2)
validate and process arg3...
}
}
Additional information:
Even though you don't see it, the default no argument constructor always calls super() first. Example:
MyClass()
{
}
is equivalent to
MyClass()
{
super();
}
I see that many have mentioned using the this and super keywords on methods and variables - all good. Just remember that constructors have unique restrictions on their usage, most notable is that they must be the very first instruction of the declared constructor and you can only use one.
this keyword use to call constructor in the same class (other overloaded constructor)
syntax: this (args list); //compatible with args list in other constructor in the same class
super keyword use to call constructor in the super class.
syntax: super (args list); //compatible with args list in the constructor of the super class.
Ex:
public class Rect {
int x1, y1, x2, y2;
public Rect(int x1, int y1, int x2, int y2) // 1st constructor
{ ....//code to build a rectangle }
}
public Rect () { // 2nd constructor
this (0,0,width,height) // call 1st constructor (because it has **4 int args**), this is another way to build a rectangle
}
public class DrawableRect extends Rect {
public DrawableRect (int a1, int b1, int a2, int b2) {
super (a1,b1,a2,b2) // call super class constructor (Rect class)
}
}

Categories

Resources