Sequence of calling super's constructor in Java

S

Sathyaish

I have some questions about calling constructors in Java:

1) Do I *have* to call the base/super class constructor from the
child's constructor as the *first* line of code or can I call it
afterwards also from within the child class' constructor?

As in, do I have to do this?

class Child extends Parent
{
public Child(somearg)
{
/* call the parent's constructor first */
super(somearg);

/* other stuff here */
}
}


Or do I have the liberty to do this?

class Child extends Parent
{
public Child(somearg)
{
/* some stuff first happens here */

/* later */
super(somearg);
}
}


I recall reading somewhere that the call to super has to be first line
of code in a child's constructor.

2) Does Java implicitly call super even when we don't explicitly call
it from a child? It makes sense because that is how object invocation
is sequenced. However, how does it know the params to pass? Or does it
do it call the non-parameterized constructor of the super class?
Because how else will it know of what parameters to pass?

3) Supposing the answer to question 2 above is "Yes, Java does call
non-parameterized constructors implicitly first, in order to create
the parent before creating the child," even then, can I explicitly
call the parent's constructor as indicated in question (1) (b) above?
 
S

Sathyaish

*PARTLY RESOLVED*

This quote:

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.

from this link: http://java.sun.com/docs/books/tutorial/java/IandI/super.html

answers questions (2) and (3).

Can someone please answer my question (1).
 
S

Sathyaish

*FULLY RESOLVED*

1. Yes. It has to be the first statement.

2. As indicated by the note and the link above, Java will call the
base's non-parameterized constructor implicitly if a parameterized one
is not called as the first line of code. If the base class is a class
other than System.Object and the base class doesn't have one, it'll
complain.

3. If the base's parameterized constructor is called by the child's
constructor as the first line explicitly, no problem. If the base's
parameterized constructor is called explicitly by the child *later*
than the first line, the compiler will complain because it will expect
JRE to instantiate the object already in the first line by the
implicit call to the naked constructor.
 
E

Eric Sosman

Sathyaish wrote On 04/05/07 10:15,:
*FULLY RESOLVED*

1. Yes. It has to be the first statement.

(It would be nicer to quote enough context so someone
can know what Question 1 is without scrambling backwards
through the thread thickets ...)

For those tuning in late, Question 1 asked whether the
call to the superclass constructor had to be the first
statement in a subclass constructor, or whether it could
come later. As Sathyaish has discovered, it must be first.

In some cases, you may need to execute a few statements
to generate the arguments you need for the super-constructor.
You cannot do something like

SubClass(double[] array) {
double total = 0;
for (double d : array)
total += d;
// pass array average to superclass constructor:
super(total / array.length);
...
}

.... because the call to super is not first. What you *can*
do, though, is move the interfering statements to a method
of their own:

SubClass(double[] array) {
super(meanOfArray(array));
...
}

private static double meanOfArray(double[] array) {
... find and return the mean ...
}

If you need to use this trick, make sure that the "helper"
method cannot be overridden in a sub-subclass! It will run
before the SubClass instance is fully initialized -- even
before the SuperClass instance is initialized -- so you can
get lots of peculiar trouble if it tries to do something with
the incompletely initialized object. Making it private and/or
static, as above, is a good defense against that error.
 
L

Lew

Eric said:
If you need to use this trick, make sure that the "helper"
method cannot be overridden in a sub-subclass! It will run
before the SubClass instance is fully initialized -- even
before the SuperClass instance is initialized -- so you can
get lots of peculiar trouble if it tries to do something with
the incompletely initialized object. Making it private and/or
static, as above, is a good defense against that error.


Joshua Bloch goes into this point in /Effective Java/.

Never call overridable methods from a constructor.

Generally, don't do very much work in the constructor. Never do work in the
constructor not related to construction of the object.
 
P

Piotr Kobzda

Making it static is the only choice for a "trick", hence it can not be
overridden. Instance of the class being initialized is not yet
available, so worry about its initialization is not needed here.
Joshua Bloch goes into this point in /Effective Java/.

Never call overridable methods from a constructor.

That's impossible in Eric's "trick".

SubClass() { // constructor
SuperClass( /* 'this' is not available here! */ );

// that's what J. Bloch is dissuading from doing
overridableMethod();
...

Generally, don't do very much work in the constructor. Never do work in
the constructor not related to construction of the object.

Agreed.


piotr
 
C

Chris Uppal

Eric said:
If you need to use this trick, make sure that the "helper"
method cannot be overridden in a sub-subclass!

The compiler won't let you call code which could be overriden in this trick.
It is illegal (rejected by the verifier even if the compiler allowed it) to
make any use of "this" before the superclass constructor has been called[*].
So you are restricted to using static methods, or code which otherwise makes no
reference to the object under construction.

-- chris

[*] There are a few technical quibbles here, but they probably aren't relevant
for this thread.
 
P

Piotr Kobzda

Piotr said:
Lew wrote:

That's impossible in Eric's "trick".

Or, that's the only possibility for a "trick". The answer depends what
sense of the statement it refers to.[1] :)
SubClass() { // constructor
SuperClass( /* 'this' is not available here! */ );

Of course, correct syntax is:

super( /* 'this' is not available here! */ );
// that's what J. Bloch is dissuading from doing
overridableMethod();
...


piotr


[1] -- I don't know, if for all English speakers the main sense
distinction is obvious here -- for me, it isn't. English is not my
native language, hence it sometimes appears difficult to me to get a
right sense of the sentence, especially in context of discussion in mind.

BTW, it sometimes happens also that my English sentences are not correct
(even though I'm hardly trying to avoid it), and they are possibly not
even understandable for others. My apologies to all for that.
 
G

Gordon Beaton

BTW, it sometimes happens also that my English sentences are not
correct (even though I'm hardly trying to avoid it), and they are
possibly not even understandable for others.

I don't normally comment on language style, but just couldn't resist
here, given the context: "hardly trying" means the opposite of "trying
hard", which is what I think you meant to say.

/gordon

--
 
P

Piotr Kobzda

Gordon said:
I don't normally comment on language style, but just couldn't resist
here, given the context: "hardly trying" means the opposite of "trying
hard", which is what I think you meant to say.

Yes, that's what I meant. :) Thanks!


piotr
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,121
Latest member
LowellMcGu
Top