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 / May 2006

Tip: Looking for answers? Try searching our database.

Initialization & Inheritance

Thread view: 
Christian Pontesegger - 19 May 2006 22:19 GMT
Hi all,

for a recent project I was trying to initialize members of a derived
class from the constructor of the super class (done using an abstract
method). This is an example code:

public abstract class Base {
    public Base() {
        init();
    }

    protected abstract void init();
}

public class Derived extends Base {

    private int foo = 0;

    public Derived() {
        super();
    }

    protected void init() {
        foo = 5;
    }

    public static void main(String[] argv) {
        System.out.println((new Derived()).foo);
    }
}

Running this example will print "0". As I understand it Base calls
Derived.init, which sets the value to 5. Afterwards the constructor of
Derived is called and foo is reinitialized. This seems strange to me. I
expected either initialization of all members done before any
constructor is called or an error when trying to access a member which
isn't properly initialized.

Now I know how to get my intended behavior, just don't initialize foo =
"0" and this program will return "5" as expected (at least by me).

But is this behavior mentioned above a design problem or is it even
useful and I can't see the meaning of it?

thanks
Christian Pontesegger
Eric Sosman - 19 May 2006 23:19 GMT
Christian Pontesegger wrote On 05/19/06 17:19,:
> Hi all,
>
[quoted text clipped - 33 lines]
> constructor is called or an error when trying to access a member which
> isn't properly initialized.

   Initializing all members before calling the constructor
is a non-starter.  Conceptually, all those initializations
are magically inserted at the start of every constructor in
the class -- indeed, if you disassemble the byte code for a
class with just one constructor, you'll see that the compiler
does exactly that.  Member initialization is part of instance
construction.

   Detecting non-initialization at run time would require a
way of tagging the uninitialized data, and maintaining and
testing the tag on each access.  That sort of thing would be
pretty expensive[*] -- and besides, it wouldn't change the
behavior of your example!  Your problem isn't failure to
initialize, but double initialization.

   [*] I recall a long-ago system that managed to do this.
All variable references were indirect through a symbol table
that contained a pointer to the actual memory location where
the data lived.  As initialized, all the pointers aimed one
byte too high; if you used the pointer as it stood, you'd get
a bad-alignment trap from the hardware.  But when a variable
was written, the code first cleared the low-order bit of the
pointer in the table, so all subsequent references found a
properly-aligned pointer.  This was probably the cheapest
uninitialized-variable catcher I've ever seen, yet it doubled
the cost of every read and tripled the cost of every write.

> Now I know how to get my intended behavior, just don't initialize foo =
> "0" and this program will return "5" as expected (at least by me).
>
> But is this behavior mentioned above a design problem or is it even
> useful and I can't see the meaning of it?

   The "design problem," I think, is the double initialization
of foo.  If you want to initialize it at the point of declaration
then go ahead and do so -- but don't turn around and re-initialize
it in init().  If you want to rely on init(), don't initialize in
the declaration.  Choose one way or the other but not both.

   Another way to view things is to note that you've violated
one of the Big Rules: Never let a constructor call an overridable
method on the object being constructed.  The reason for the
prohibition is to avoid exactly the sort of situation you've run
into here, where an overriding method gets its hands on an
incompletely initialized object.

Signature

Eric.Sosman@sun.com

Tony Morris - 19 May 2006 23:35 GMT
> Hi all,
>
[quoted text clipped - 42 lines]
> thanks
> Christian Pontesegger

Here is another example that demonstrates your observation:
http://jqa.tmorris.net/GetQAndA.action?qids=10&showAnswers=true
You are simply observing one of the many flaws of behaviour inheritance -
which implies some knowledge about the future.
http://contractualj.com/ "All classes are declared final. Concrete behaviour
inheritance is not permitted."

--
Tony Morris
http://tmorris.net/


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



©2008 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.