Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / April 2007

Tip: Looking for answers? Try searching our database.

Initialization order brain-damage

Thread view: 
Dave  Rush - 14 Apr 2007 15:44 GMT
Hi y'all,

So after spending a particularly frustrating afternoon debugging
through constructors and browsing the Java Language Specification 3.0
in some detail, I have come to the conclusion that I actually know
nothing and need to ask a question:

What is the standard order of evaluation of expressions during object
construction w/rt constructors, super-constructors, and instance
variable initializers? Specifically with the code:

class A
{
AType a1 = new AType();

A() { aDoesSomething(); }
}

class B extends A
{
AnotherType b1 = new AnotherType();

B() { bDoesSomethingElse(); }
}

B bongo = new B();

when do all of the various bits get executed? If there's a section of
the language spec that tells me this, I would really appreciate the
pointer, as well...

david rush
Lew - 14 Apr 2007 15:57 GMT
Dave Rush wrote:
> Hi y'all,
>
[quoted text clipped - 26 lines]
> the language spec that tells me this, I would really appreciate the
> pointer, as well...

Assuming you mean during the call to new B(),

Space for new B is allocated
superclass default constructor
new AType()
aDoesSomething() <== better not be significant or overridable or have to do
with anything other than constructing an A
new AnotherType()
bDoesSomethingElse() <== better not be significant or overridable or have to
do with anything other than constructing a B

<http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.8.7.1>

Signature

Lew

Stefan Ram - 14 Apr 2007 16:03 GMT
>What is the standard order of evaluation of expressions during
>object construction w/rt constructors, super-constructors, and
>instance variable initializers? Specifically with the code:

 instance initialization

     »memory space is allocated for it with room for all the
     instance variables declared in the class type and all the
     instance variables declared in each superclass [...] All
     the instance variables in the new object, including those
     declared in superclasses, are initialized to their default
     values [...] evaluate the arguments and process [explicit
     or implicit] constructor invocation recursively using
     these same five steps. [...] Execute the instance
     initializers and instance variable initializers [...] in
     the left-to-right order in which they appear textually in
     the source code for the class. [...] Execute the rest of
     the body of this constructor.«

   JLS3, 12.5

http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.5

 instance initializer

     »Instance initializers (§8.6) are blocks of executable
     code that may be used to help initialize an instance when
     it is created (§15.9).«

   JLS3, 8 Classes

http://java.sun.com/docs/books/jls/third_edition/html/classes.html

 instance variable initializer

     »Initialization expressions for instance variables«

   JLS3, 8.3.2.2 Initializers for Instance Variables

http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.3.2.2
Stefan Ram - 14 Apr 2007 16:23 GMT
>JLS3, 12.5

 Simplified and in my wording:

     0  set fields to default values as they are specified by
        the language

     1  invoke the (implicit or constructor-called)
        super-constructor and perform steps 1-3 for the superclass

     2  do the explicit initializations (variable and instance
        initializers) in the source-code order

     3  execute the rest of the constructor
Stefan Ram - 14 Apr 2007 16:49 GMT
>0  set fields to default values as they are specified by
>   the language
[quoted text clipped - 3 lines]
>   initializers) in the source-code order
>3  execute the rest of the constructor

 e.g.,

class B
{ int a = Do.print( "B0" );
 { Do.print( "B1" ); }
 int b = Do.print( "B2" );
 public B(){ Do.print( "B4" ); }
 { Do.print( "B3" ); }}

class A extends B
{ int c = Do.print( "A0" );
 { Do.print( "A1" ); }
 int d = Do.print( "A2" );
 public A(){ Do.print( "A4" ); }
 { Do.print( "A3" ); }}

public class Main
{
 public static void main( final java.lang.String[] args )
 { new A(); }}

class Do
{ public static int print( final java.lang.String text )
 { java.lang.System.err.println( text ); return 1; }}

/* prints
B0
B1
B2
B3
B4
A0
A1
A2
A3
A4
*/
Patricia Shanahan - 14 Apr 2007 17:36 GMT
>> JLS3, 12.5
>
[quoted text clipped - 10 lines]
>
>       3  execute the rest of the constructor

Excellent summary. Do you think it would be possible to avoid the
appearance of unbounded recursion without making it too detailed and
complicated? Something like this:

      0  set fields to default values as they are specified by
         the language

      1  If not in new Object() constructor invoke the (implicit
         or constructor-called) super-constructor and perform
         steps 1-3 for the superclass

      2  do the explicit initializations (variable and instance
         initializers) in the source-code order

      3  execute the rest of the constructor

It also does not deal with this() on the first line of a constructor,
but I can't see how to fold that in without making it too complicated.
This is obviously a trade-off between level of detail and being clearer
than the JLS description.

Patricia
Stefan Ram - 14 Apr 2007 18:31 GMT
>If not in new Object() constructor invoke the (implicit

 Thanks for the correction! I already was aware of this
 inaccuracy and am accepting it for the sake of
 simplification. Feel free to use and publish the list of steps
 including this modification regarding the class »Object«,
 while I might not add it to my own list.
Dave  Rush - 17 Apr 2007 20:00 GMT
> >JLS3, 12.5
>       2  do the explicit initializations (variable and instance
>          initializers) in the source-code order

This is the piece of the text in 12.5 that my brain just kept blipping
over. The verbage is dreadful. Thank you so much for the help.

I should add that I think this is broken behavior! If a subclass
overrides a method used in a superclass contructor that needs an
initialized field in the subclass, you're just completely hosed. You
have to resort to copy&paste reuse or a lazy initializer via a getter
method. Leaving the desirability of accessing all instance vars
through getters aside for the moment, this leaves open a rather large
hole for non-obvious bugs in systems with high-levels of black-box
reuse as are commonly being built in Java today.

david
--
(and yes I coded my way around this days ago using a lazy init...just
wanted to know if it was in fact mandatory to do so)
Tom Hawtin - 17 Apr 2007 20:39 GMT
Dave Rush wrote:
>>> JLS3, 12.5
>>       2  do the explicit initializations (variable and instance
[quoted text clipped - 6 lines]
> overrides a method used in a superclass contructor that needs an
> initialized field in the subclass, you're just completely hosed. You

But if you want initialiser code to access this (say, an inner class),
you would be hosed if super had not been called.

Don't call overrideable methods from constructors (unless specifically
designed otherwise).

Tom Hawtin
David  Rush - 17 Apr 2007 21:45 GMT
Poo. It looks like the Google groups interface just ate my well-
thought-out and carefully reasoned post. This means that this one is
my grumpy migraine-influenced version...

> Dave Rush wrote:
> >>> JLS3, 12.5
[quoted text clipped - 7 lines]
> But if you want initialiser code to access this (say, an inner class),
> you would be hosed if super had not been called.

Well, potayto, potahto. Gripping hand is that there is no way to run
anything before the superclass constructor code. This is good if you
like flexibility in your reuse patterns, bad if you fear people
reusing your code in surprising ways. So basically the standard
supports incompetent programmers rather than enabling competent ones.

> Don't call overrideable methods from constructors (unless specifically
> designed otherwise).

Well the call of the overridable method wasn't in *my* code. It was in
a 3rd party constructor's and I had no control over that code. This
particular control had gotten good reviews on various java community
sites and has been around for more than a few years, so I expected the
code to be relatively mature. So basically your preaching "never reuse
any black-box code", which is reasonable, but terribly unfashionable
just now.

And do you really want the compiler to barf on any calls of non-final/
non-private methods in a constructor?

david
Patricia Shanahan - 14 Apr 2007 16:05 GMT
Dave Rush wrote:
> Hi y'all,
>
[quoted text clipped - 26 lines]
> the language spec that tells me this, I would really appreciate the
> pointer, as well...

The best overall description that I've found is at:

http://java.sun.com/docs/books/jls/third_edition/html/execution.html#44670

12.5 Creation of New Class Instances

Patricia


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.