how to pass this before supertype constructor has been called

Discussion in 'Java' started by Paul J. Lucas, Nov 26, 2003.

  1. Given:

    // Other.java
    class Other {
    Other( Base b ) {
    m_b = b;
    }
    final Base m_b;
    }

    // Base.java
    class Base {
    Base( Other o ) {
    m_o = o;
    }
    final Other m_o;
    }

    // Derived.java
    class Derived extends Base {
    static class Inner1 extends Other {
    Inner1( Base b ) {
    super( b );
    }
    static class Inner1a extends Other {
    // ...
    }
    }
    static class Inner2 extends Other {
    // ...
    }

    Derived() {
    super( new Inner1( this ) ); // illegal
    }
    }

    There are many inner classes derived from Other. All of them
    need to have a reference to their outermost creating instance
    of Derived. (This is machine-generated code in case you're
    wondering.) But it's illegal to pass "this" as shown above
    (although there is no reason for this restriction since it's
    just an address in memory which is already known. C++ has no
    such restriction.)

    How can I get what I want in Java?

    - Paul
    Paul J. Lucas, Nov 26, 2003
    #1
    1. Advertising

  2. "Paul J. Lucas" <> schrieb im
    Newsbeitrag news:li6xb.57854$...
    > Given:
    >
    > // Other.java
    > class Other {
    > Other( Base b ) {
    > m_b = b;
    > }
    > final Base m_b;
    > }
    >
    > // Base.java
    > class Base {
    > Base( Other o ) {
    > m_o = o;
    > }
    > final Other m_o;
    > }
    >
    > // Derived.java
    > class Derived extends Base {
    > static class Inner1 extends Other {
    > Inner1( Base b ) {
    > super( b );
    > }
    > static class Inner1a extends Other {
    > // ...
    > }
    > }
    > static class Inner2 extends Other {
    > // ...
    > }
    >
    > Derived() {
    > super( new Inner1( this ) ); // illegal
    > }
    > }
    >
    > There are many inner classes derived from Other. All of them
    > need to have a reference to their outermost creating instance
    > of Derived. (This is machine-generated code in case you're
    > wondering.) But it's illegal to pass "this" as shown above
    > (although there is no reason for this restriction since it's
    > just an address in memory which is already known. C++ has no
    > such restriction.)
    >
    > How can I get what I want in Java?
    >
    > - Paul



    I'm not sure if there really is no reason to permit the usage
    of "this" before the object is fully created (although you really pass
    only an address).

    You say the code is machine-generated!? So the "machine" is
    responsible to generate legal java code. On the other hand
    if this "machine"-program was adaptet from an existing
    C++ source you can slightly change it to produce a setter
    method that actually does the setting. Likely as:


    // Other.java
    class Other {
    void setBase(Base b) {m_b = b;}
    Base m_b;
    }

    // Base.java
    class Base {
    void setOther(Other other) {m_o = other;}
    Other m_o;
    }

    // Derived.java
    class Derived extends Base {
    static class Inner1 extends Other {
    static class Inner1a extends Other {
    }
    }
    static class Inner2 extends Other {
    }

    Derived() {
    //super( new Inner1( this ) ); // illegal
    Other inner1 = new Inner1();
    inner1.setBase(this);
    setOther(inner1);
    }
    }

    This uses a little more code but it doesn't matter if it's
    machine-generated.

    The only problem is that the references are no longer final and therefore
    should be private.

    In order to avoid later invocations of setXXX(...) the setXXX methods
    should test if the instance variable is still null

    Bye
    Mustafa
    Mustafa Aydin, Nov 27, 2003
    #2
    1. Advertising

  3. Mustafa Aydin <> wrote:

    > You say the code is machine-generated!? So the "machine" is
    > responsible to generate legal java code.


    Yes I know: I'm the one trying to write the machine to do just
    that.

    > On the other hand if this "machine"-program was adaptet from an existing C++
    > source you can slightly change it to produce a setter method that actually
    > does the setting.


    Yes, but that's a stupid hack.

    > The only problem is that the references are no longer final and therefore
    > should be private.


    Right. I was hoping to avoid that ugly hack, however.

    - Paul
    Paul J. Lucas, Nov 28, 2003
    #3
  4. Paul J. Lucas wrote:

    > Given:
    >
    > // Other.java
    > class Other {
    > Other( Base b ) {
    > m_b = b;
    > }
    > final Base m_b;
    > }
    >
    > // Base.java
    > class Base {
    > Base( Other o ) {
    > m_o = o;
    > }
    > final Other m_o;
    > }
    >
    > // Derived.java
    > class Derived extends Base {
    > static class Inner1 extends Other {
    > Inner1( Base b ) {
    > super( b );
    > }
    > static class Inner1a extends Other {
    > // ...
    > }
    > }
    > static class Inner2 extends Other {
    > // ...
    > }
    >
    > Derived() {
    > super( new Inner1( this ) ); // illegal
    > }
    > }
    >
    > There are many inner classes derived from Other. All of them
    > need to have a reference to their outermost creating instance
    > of Derived. (This is machine-generated code in case you're
    > wondering.) But it's illegal to pass "this" as shown above
    > (although there is no reason for this restriction since it's
    > just an address in memory which is already known. C++ has no
    > such restriction.)


    C++ has no restrictions against many things that can in fact be harmful.
    By design, Java is much more careful. In the parts of the example
    that show real code, you can be confident that the Derived instance is
    not used unsafely before it is fully initialized, but one cannot make
    such an assumption in general.

    > How can I get what I want in Java?


    It depends on what it is you want. You cannot do exactly what you are
    trying to do, but you already knew that.

    It might be that making the nested classes be inner classes (by removing
    the "static" modifiers) would solve the problem while simultaneously
    simplifying the object construction process. An inner class instance
    automatically has references (hidden, yet accessible) to all containing
    instances, and can directly access those instances' members.


    John Bollinger
    John C. Bollinger, Dec 1, 2003
    #4
  5. John C. Bollinger <> wrote:

    > C++ has no restrictions against many things that can in fact be harmful. By
    > design, Java is much more careful.


    I'm not going to get into a langauge war with you. Suffice it
    to say that *I* should be the one allowed to make such
    decisions.

    Either you have a solution to my problem of you don't.

    > In the parts of the example that show real code, you can be confident that
    > the Derived instance is not used unsafely before it is fully initialized ...


    How can the Base class use it in any way whatsoever? It's
    totally unaware of the derived class.

    > It might be that making the nested classes be inner classes (by removing
    > the "static" modifiers) would solve the problem while simultaneously
    > simplifying the object construction process.


    Did you try it? It doesn't work for the same reason.

    > An inner class instance automatically has references (hidden, yet accessible)
    > to all containing instances, and can directly access those instances'
    > members.


    Yes, I already knew that. How else would I have known to put
    "static" there in the first place? Clearly I had to know what
    the default is and what "static" does.

    - Paul
    Paul J. Lucas, Dec 1, 2003
    #5
  6. Paul J. Lucas wrote:

    > John C. Bollinger <> wrote:
    >
    >
    >>C++ has no restrictions against many things that can in fact be harmful. By
    >>design, Java is much more careful.

    >
    >
    > I'm not going to get into a langauge war with you. Suffice it
    > to say that *I* should be the one allowed to make such
    > decisions.


    And you make several such decisions by choosing Java.

    I apologize that you found my comment inflammatory; perhaps "dangerous"
    would have been a better word than "harmful". In any event, the point
    is that Java is by design rather more picky and restrictive than is C++
    in several areas; this is widely recognized and has both advantages and
    disadvantages.

    > Either you have a solution to my problem of you don't.


    That sounds like a pretty safe bet. :)

    >>In the parts of the example that show real code, you can be confident that
    >>the Derived instance is not used unsafely before it is fully initialized ...

    >
    >
    > How can the Base class use it in any way whatsoever? It's
    > totally unaware of the derived class.


    Base could in fact use it if it invoked a method that Derived had
    overridden -- a dangerous practice that is nevertheless allowed in Java.
    Base could also use it indirectly via the Other instance supplied to
    its constructor. But I was also talking about the Inner1, Inner2, etc.
    constructors using it.

    >>It might be that making the nested classes be inner classes (by removing
    >>the "static" modifiers) would solve the problem while simultaneously
    >>simplifying the object construction process.

    >
    >
    > Did you try it? It doesn't work for the same reason.


    No, I didn't try it. And I wrote that it _might_ work. I'm sorry that
    it didn't.

    I take it you don't intend to honor my invoice?

    >>An inner class instance automatically has references (hidden, yet accessible)
    >>to all containing instances, and can directly access those instances'
    >>members.

    >
    >
    > Yes, I already knew that. How else would I have known to put
    > "static" there in the first place? Clearly I had to know what
    > the default is and what "static" does.


    Yes, there is only one possible explanation for the static modifiers on
    those classes. There is no chance that they were copied from some
    not-necessarilly-relevant and not fully understood example. There is no
    chance that your code generator puts them in without good reason. There
    is no chance that you misunderstand the meaning of "static" in Java,
    which does not precisely match its meaning in C++ (with which you
    expressed familiarity). Of course all those who post questions to this
    forum are already well versed in Java. (Otherwise, how could they come
    up with such clever questions?)




    With regard to your actual problem, here is an inner-class-based
    solution that works for me:


    class Other {
    }

    abstract class Base {
    final Other other;

    Base() {
    other = getOther();
    }

    abstract protected Other getOther();
    }

    class Derived extends Base {
    class Inner1 extends Other {
    }

    public Derived() {
    }

    protected Other getOther() {
    return new Inner1();
    }
    }


    It does use the dangerous practice described above of the superclass'
    constructor invoking a method of the derived class. The Inner1
    constructor must not depend on Derived's state if this is to work (but
    otherwise no solution of this general kind can work). A better solution
    might be to redesign the object relationships, but more information
    about the purpose and usage of the classes involved would be necessary
    to make that determination.


    John Bollinger
    John C. Bollinger, Dec 1, 2003
    #6
  7. Paul J. Lucas

    Dale King Guest

    "Paul J. Lucas" <> wrote in message
    news:li6xb.57854$...
    > Given:
    >
    > // Other.java
    > class Other {
    > Other( Base b ) {
    > m_b = b;
    > }
    > final Base m_b;
    > }
    >
    > // Base.java
    > class Base {
    > Base( Other o ) {
    > m_o = o;
    > }
    > final Other m_o;
    > }



    The derived and inner classes are really not the issue here. Basically you
    have a chicken and an egg problem with these two classes. You cannot have an
    instance of Other before you have an instance of Base and you cannot have an
    instance of Base before you have an instance of Other.

    There is no way out of that circularity outside of using null to create an
    instance referring to no instance. Trying to get a reference to an
    uninitialized instance by subclassing is not allowed of course and rightly
    so..

    You need to rethink your design. The java.io classes PipedInputStream and
    PipedOutputStream have a similar scenario and you should take a look at how
    they solve it. You basically have to allow one end of the two classes to be
    able to be constructed before the other.

    --
    Dale King
    --
    Dale King
    Dale King, Dec 1, 2003
    #7

  8. > C++ has no restrictions against many things that can in fact be harmful.
    > By design, Java is much more careful. In the parts of the example that
    > show real code, you can be confident that the Derived instance is not
    > used unsafely before it is fully initialized, but one cannot make such
    > an assumption in general.


    There is something I don't get. For the same reason it should then be
    necessary to disable polymorphism in the constructor, but as far as I
    know polymorphism is not disabled. That is, in the constructor of the
    derived class you can use members that are not yet initialized.
    I don't see a big difference here.

    Andrea
    Andrea Desole, Dec 2, 2003
    #8
  9. Andrea Desole wrote:

    >
    >> C++ has no restrictions against many things that can in fact be
    >> harmful. By design, Java is much more careful. In the parts of the
    >> example that show real code, you can be confident that the Derived
    >> instance is not used unsafely before it is fully initialized, but one
    >> cannot make such an assumption in general.

    >
    >
    > There is something I don't get. For the same reason it should then be
    > necessary to disable polymorphism in the constructor, but as far as I
    > know polymorphism is not disabled. That is, in the constructor of the
    > derived class you can use members that are not yet initialized.
    > I don't see a big difference here.


    If you mean that the constructor of the base class can manipulate
    uninitialized members of the derived class via polymorphic methods of
    the derived class then you're right, it's an inconsistency in the
    language design. I suspect that it was allowed either as an oversight
    or to simplify JVM / compiler implementation. Either way, it allows
    working around the language restriction in this case, which may or may
    not be a good thing. It does require the cooperation of the derived
    class, however, so there is at least some degree of protection.


    John Bollinger
    John C. Bollinger, Dec 2, 2003
    #9
  10. Paul J. Lucas

    Tim Ward Guest

    "John C. Bollinger" <> wrote in message
    news:bqi6ga$9ik$...
    >
    > If you mean that the constructor of the base class can manipulate
    > uninitialized members of the derived class via polymorphic methods of
    > the derived class then you're right, it's an inconsistency in the
    > language design. I suspect that it was allowed either as an oversight
    > or to simplify JVM / compiler implementation. Either way, it allows
    > working around the language restriction in this case, which may or may
    > not be a good thing. It does require the cooperation of the derived
    > class, however, so there is at least some degree of protection.


    Once you've worked out what's going on.

    Try deriving from JTable, for example, and you'll find all sorts of your
    derived class methods being called before the constructor has run. Sure, you
    can put in protective code, to make sure these methods don't crash until
    things have been properly intialised, but this protective code then, of
    course, runs every time the derived methods are called giving a completely
    unnecessary overhead.

    The author of JTable appears to have failed to spot, or to have decided not
    to adhere to, the suggested rule the one might consider avoiding calling
    polymorphic methods in constructors.

    --
    Tim Ward
    Brett Ward Limited - www.brettward.co.uk
    Tim Ward, Dec 2, 2003
    #10
  11. John C. Bollinger <> wrote:
    > Paul J. Lucas wrote:


    > And you make several such decisions by choosing Java.


    I didn't choose Java. I'm only implementing a Java version to
    have broader appeal.

    >> How can the Base class use it in any way whatsoever? It's
    >> totally unaware of the derived class.

    >
    > Base could in fact use it if it invoked a method that Derived had
    > overridden -- a dangerous practice that is nevertheless allowed in Java.


    Yeah and that one seems contradictory to everything you said
    earlier.

    > Yes, there is only one possible explanation for the static modifiers on
    > those classes. There is no chance that they were copied from some
    > not-necessarilly-relevant and not fully understood example. There is no
    > chance that your code generator puts them in without good reason.


    I'm the one writing the code generator.

    > With regard to your actual problem, here is an inner-class-based
    > solution that works for me:


    But it doesn't pass "this", so how is this a solution?

    - Paul
    Paul J. Lucas, Dec 2, 2003
    #11
  12. Dale King <> wrote:

    > Basically you have a chicken and an egg problem with these two classes. You
    > cannot have an instance of Other before you have an instance of Base and you
    > cannot have an instance of Base before you have an instance of Other.


    I never said I needed an "instance" of the derived class. All
    I care about is its "this" reference which *is* known at the
    time the Derived constructor is running. But Java simply
    doesn't allow you to refer to it because of "safety."

    > You need to rethink your design.


    You need to re-read my original question.

    - Paul
    Paul J. Lucas, Dec 2, 2003
    #12
  13. Paul J. Lucas

    Dale King Guest

    "Paul J. Lucas" <> wrote in message
    news:3v3zb.30519$...
    > Dale King <> wrote:
    >
    > > Basically you have a chicken and an egg problem with these two classes.

    You
    > > cannot have an instance of Other before you have an instance of Base and

    you
    > > cannot have an instance of Base before you have an instance of Other.

    >
    > I never said I needed an "instance" of the derived class. All
    > I care about is its "this" reference which *is* known at the
    > time the Derived constructor is running. But Java simply
    > doesn't allow you to refer to it because of "safety."


    Funny, but I don't see where I used the word derived at all in what you
    quoted. I specifically said Base and Other. And no the this reference is not
    known until the constructor is called. You essentially do not have an
    instance of Base until its constructor is called and all its super class
    constructors have finished.

    Imagine if your Other class tried to use the Base reference in its
    constructor. Base is totally uninitialized. There are no guarantees about
    what would happen in this case. To make guarantees would place extra burden
    on the implementer of the VM.

    In this case safety is a good thing.

    > > You need to rethink your design.

    >
    > You need to re-read my original question.


    No, I don't. I understand what you are requesting completely. You have a
    chicken and the egg paradox and you think Java should let you get away with
    referencing an unconstructed object as a way to solve the paradox. You are
    wrong. Java should not let you do that. Your design is wrong.

    --
    Dale King
    Dale King, Dec 2, 2003
    #13
  14. Paul J. Lucas

    Dale King Guest

    "Dale King" <> wrote in message
    news:...
    > "Paul J. Lucas" <> wrote in message
    > news:3v3zb.30519$...
    > > Dale King <> wrote:
    > >
    > > > Basically you have a chicken and an egg problem with these two

    classes.
    > You
    > > > cannot have an instance of Other before you have an instance of Base

    and
    > you
    > > > cannot have an instance of Base before you have an instance of Other.

    > >
    > > I never said I needed an "instance" of the derived class. All
    > > I care about is its "this" reference which *is* known at the
    > > time the Derived constructor is running. But Java simply
    > > doesn't allow you to refer to it because of "safety."

    >
    > Funny, but I don't see where I used the word derived at all in what you
    > quoted. I specifically said Base and Other. And no the this reference is

    not
    > known until the constructor is called. You essentially do not have an
    > instance of Base until its constructor is called and all its super class
    > constructors have finished.
    >
    > Imagine if your Other class tried to use the Base reference in its
    > constructor. Base is totally uninitialized. There are no guarantees about
    > what would happen in this case. To make guarantees would place extra

    burden
    > on the implementer of the VM.
    >
    > In this case safety is a good thing.



    I thought of another reason why what Paul is requesting is inherently
    unsafe. Imagine if it were allowed to pass this before construction. In this
    case Other stores that reference. What happens when the constructor actually
    does run and it throws an exception? You could then have a reference to not
    only an uninitialized instance but one whose constructor failed and whose
    memory has actually been freed and is no longer even allocated!

    Once again you have a logical paradox that is a problem in your design. The
    problem is not that Java is safe. If you want help with correcting design
    you have to explain what your design represents, not just abstract classes.
    --
    Dale King
    Dale King, Dec 2, 2003
    #14
  15. Paul J. Lucas wrote:

    > John C. Bollinger <> wrote:


    >>With regard to your actual problem, here is an inner-class-based
    >>solution that works for me:

    >
    >
    > But it doesn't pass "this", so how is this a solution?


    As I wrote in a previous message, you cannot do exactly what you are
    trying to do (i.e. pass "this" from within a class' constructor).
    Period. The solution I offered provides a means to achieve an
    equivalent goal, however.

    You were attempting to construct two objects, each of which held a final
    reference to the other, with the class of one being a nested class of
    the class of the other. The solution I offered achieves precisely that.
    If there are additional requirements that you have not disclosed then
    please forgive me for not taking them into account.


    John Bollinger
    John C. Bollinger, Dec 2, 2003
    #15
  16. Dale King wrote:
    > I thought of another reason why what Paul is requesting is inherently
    > unsafe. Imagine if it were allowed to pass this before construction. In this
    > case Other stores that reference. What happens when the constructor actually
    > does run and it throws an exception? You could then have a reference to not
    > only an uninitialized instance but one whose constructor failed and whose
    > memory has actually been freed and is no longer even allocated!


    Given that I offered a workaround that basically does allow this to be
    passed before completion of the constructor, it occurred to me to test
    out that scenario. I found the result a bit shocking. Here's the code:


    class Other {
    static Other lastOther;

    final Base base;

    Other(Base b) {
    base = b;
    Other.lastOther = this;
    }

    public void foo() {
    base.foo();
    }
    }

    abstract class Base {
    private final Other other;

    Base() {
    other = getOther();
    }

    protected abstract Other getOther();

    public void foo() {
    System.out.println("Foo!");
    }
    }

    class Derived extends Base {
    class Inner extends Other {
    Inner() {
    super(Derived.this);
    }
    }

    public Derived() {
    throw new RuntimeException("Can't construct a Derived.");
    }

    protected Other getOther() {
    return new Inner();
    }
    }

    public class ReferenceTest {
    public static void main(String[] args) {
    try {
    Derived d = new Derived();
    } catch (RuntimeException re) {
    System.out.println(re);
    }
    System.out.println("Class of lastOther.base is "
    + Other.lastOther.base.getClass());
    Other.lastOther.foo();
    }
    }


    Here is the result (Java 1.4.2):

    D:\temp\testdir>java -cp . ReferenceTest
    java.lang.RuntimeException: Can't construct a Derived.
    Class of lastOther.base is class Derived
    Foo!


    Even though it is impossible to successfully construct a Derived, I can
    nevertheless obtain a reference to one and even invoke methods on it by
    using an inner class to convey the reference through the return value of
    a polymorphic method. (Yikes! What a sentence!) I haven't yet found
    anything in the JLS to forbid this, but I would sure be interested in
    hearing about such a thing. Does anyone think this behavior is a defect
    worth reporting? Is it already known? (My first inclination would be
    to guess that it is.)


    John Bollinger
    John C. Bollinger, Dec 2, 2003
    #16
  17. Tim Ward wrote:
    > "John C. Bollinger" <> wrote in message
    > news:bqi6ga$9ik$...
    >
    >>If you mean that the constructor of the base class can manipulate
    >>uninitialized members of the derived class via polymorphic methods of
    >>the derived class then you're right, it's an inconsistency in the
    >>language design. I suspect that it was allowed either as an oversight
    >>or to simplify JVM / compiler implementation. Either way, it allows
    >>working around the language restriction in this case, which may or may
    >>not be a good thing. It does require the cooperation of the derived
    >>class, however, so there is at least some degree of protection.

    >
    >
    > Once you've worked out what's going on.
    >
    > Try deriving from JTable, for example, and you'll find all sorts of your
    > derived class methods being called before the constructor has run. Sure, you
    > can put in protective code, to make sure these methods don't crash until
    > things have been properly intialised, but this protective code then, of
    > course, runs every time the derived methods are called giving a completely
    > unnecessary overhead.


    I don't know how JTable works, but I agree. There is no difference
    between enabling polymorphism and passing this in the constructor. In
    either case you have to know exactly how the base class handles the
    derived class, or you have to put in some code to protect the
    consistency of your derived class.

    Andrea
    Andrea Desole, Dec 3, 2003
    #17
  18. Paul J. Lucas

    Chris Uppal Guest

    John C. Bollinger wrote:

    > Given that I offered a workaround that basically does allow this to be
    > passed before completion of the constructor, it occurred to me to test
    > out that scenario. I found the result a bit shocking. Here's the code:
    > [snipped]


    > D:\temp\testdir>java -cp . ReferenceTest
    > java.lang.RuntimeException: Can't construct a Derived.
    > Class of lastOther.base is class Derived
    > Foo!


    Very nasty!

    The problem code can be significantly simplified (and so avoid some
    red-herrings), thus:

    ===========================
    class Base
    {
    static Base leaked;

    Base()
    {
    leaked = this;
    }

    void foo()
    {
    System.out.println("Foo!");
    }
    }

    class Derived extends Base
    {
    public Derived()
    throws Exception
    {
    throw new Exception("Can't construct a Derived.");
    }
    }

    public class RefTest
    {
    public static void main(String[] args)
    {
    try
    {
    Derived d = new Derived();
    } catch (Exception ex)
    {
    System.out.println(ex);
    }
    System.out.println("Class of Base.leaked is "
    + Base.leaked.getClass());
    Base.leaked.foo();
    }
    }
    ===========================

    > Does anyone think this behavior is a defect
    > worth reporting? Is it already known? (My first inclination would be
    > to guess that it is.)


    I certainly think its a defect. I'd guess that it's known (in the simplified
    form) already. I can't see any way to prevent it, though.

    Note that the leaked reference is left permanently in the state that would be
    seen transiently by methods of Derived that were called from Base's
    constructor, so it's really a way to blow up a small glitch in the system into
    a larger (or longer lived) one.

    I've been trying to think of ways that this could be exploited to circumvent
    security. So far, I haven't found anything -- one reason is that any state
    guarantees that the Base constructor wants to enforce are set before the object
    could be "frozen" by a derived constructor. One could possibly have some fun
    with code like:

    ===========================
    class Base
    {
    final Object blankFinal; // apparently *must* be set

    Base()
    {
    this.log("Creating a new Base");
    blankFinal = "is not null";
    }

    void log(String message)
    {
    System.out.println(message);
    }
    }

    class LeakyException
    extends RuntimeException
    {
    Base base;

    LeakyException(String message, Base base)
    {
    super(message);
    this.base = base;
    }
    }

    class Drill
    extends Base
    {
    void log(String message)
    {
    // ha ha!
    throw new LeakyException("Woops!", this);
    }
    }

    public class RefTest
    {
    public static void main(String[] args)
    {
    try
    {
    new Drill();
    } catch (LeakyException ex)
    {
    System.out.println(ex);
    System.out.println("leaked blankFinal is "
    + ex.base.blankFinal);
    }
    }
    }
    ===========================

    -- chris
    Chris Uppal, Dec 3, 2003
    #18
  19. Dale King <> wrote:

    > And no the this reference is not known until the constructor is called.


    Of course it is. It has to be. The constructor has nothing to
    do with it. For a class with neither base nor derived classes,
    the steps are:

    1. Programmer calls "new SomeObject()"
    2. JVM allocates memory from the heap for sizeof( SomeObject ).
    3. Calls SomeObject() constructor with "this" set to point to
    memory allocated in step 2.
    4. Programmer does stuff inside constructor code like
    initialize member variables.

    The only thing that is different if SomeObject has a base class,
    is that it is up to the *programmer* in step 4 to call super().
    The address of "this" MUST STILL BE KNOWN.

    > You have a chicken and the egg paradox


    No I don't. I can do what I want in C++ just fine. As long as
    I don't try to access anything *through* "this" I'm fine. It'd
    perfectly safe. It's 100% portable. It just works.

    > and you think Java should let you get away with referencing an unconstructed
    > object as a way to solve the paradox. You are wrong. Java should not let you
    > do that.


    It's not a paradox. Sorry you just can't see that.

    - Paul
    Paul J. Lucas, Dec 3, 2003
    #19
  20. Dale King <> wrote:

    > What happens when the constructor actually does run and it throws an
    > exception?


    Nothing at all.

    > You could then have a reference to not only an uninitialized instance but one
    > whose constructor failed and whose memory has actually been freed and is no
    > longer even allocated!


    But the base class holding that reference doesn't exist either
    since they're the same exact object. A derived instance has a
    base instance inside it. Both their "this" pointers point to
    the exact same memory location. If the derived object has been
    freed, then (obviously) the base object (inside it) has also.

    > Once again you have a logical paradox that is a problem in your design.


    Once again you don't see that there's no paradox.

    - Paul
    Paul J. Lucas, Dec 3, 2003
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. tshad
    Replies:
    8
    Views:
    3,298
    Marian Kostal
    Jan 11, 2007
  2. Replies:
    8
    Views:
    456
    Simon Brooke
    Oct 4, 2006
  3. Replies:
    1
    Views:
    17,907
  4. Michele Simionato
    Replies:
    11
    Views:
    442
    vasudevram
    Dec 23, 2006
  5. Dave DiFilippo
    Replies:
    0
    Views:
    824
    Dave DiFilippo
    Feb 24, 2009
Loading...

Share This Page