this reference in Java constructors

A

ankur

I am confused. My question is how can "this" reference be available in
a Java constructor ? After all, the current object ( to which "this"
refers to) has not been completely constructed yet, because we are
still in the constructor.

In this code why was the constructor able to call getVal() method even
though the call to constructor has not returned yet and so the object
is not constructed !

package threadspack;

public class MySimpleClass {

private int j;

public MySimpleClass (int val)

{
System.out.println("hello");
this.j = val;
this.getVal();

}

public void getVal()
{
System.out.println(this.j);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new MySimpleClass(5);
}

}
 
M

markspace

ankur said:
I am confused. My question is how can "this" reference be available in
a Java constructor ? After all, the current object ( to which "this"
refers to) has not been completely constructed yet, because we are
still in the constructor.
public class MySimpleClass {
private int j;
public MySimpleClass (int val)
{
this.j = val;

What Peter said.

The object has been allocated on the heap, so it can be accessed now.
Look at the last line I quoted above. You have to have "this" so that
you can initialize variables. How else would you do that with out
"this", either explicitly or implicitly?

Ditto for instance methods. The object exists so they can be called.
Calling a non-private method in a non-final class is a bit risky though,
since the method could be overridden latter to do bad things. It's best
to only call private instance methods from the constructor.
 
J

Joshua Cranmer

I am confused. My question is how can "this" reference be available in
a Java constructor ? After all, the current object ( to which "this"
refers to) has not been completely constructed yet, because we are
still in the constructor.

The more technical answer:

When you construct an object with new Foo();, this is the bytecode
generated (roughly):

anew Foo
dup
invokespecial Foo#<init>()V
[the last reference on the stack you are free to do what you will with

The anew instruction allocates memory and zero-fills it (setting default
values), then it builds the dispatch tables, and then you start invoking
constructors. So any time after the anew, a reference is /usable/.
|this| clearly exists by the time you get to the constructor. After all,
you call the constructor as a method on that instance.
In this code why was the constructor able to call getVal() method even
though the call to constructor has not returned yet and so the object
is not constructed !

You can call methods, since the |this| exist and the dispatch tables
exist. Yes, you are correct in saying that the object isn't
constructed, which is why such actions are not recommended, unless
getVal() were either final (or the class itself were final) or private.
 
E

Eric Sosman

Thomas said:
According to Joshua Cranmer said:
The more technical answer:

When you construct an object with new Foo();, this is the bytecode
generated (roughly):

anew Foo
dup
invokespecial Foo#<init>()V
[the last reference on the stack you are free to do what you will with

Just for completeness: the JVM also verifies that whenever an object is
created (with the 'new' ocode) then a call to a constructor necessarily
follows, before any other use of the reference to the new instance. The
JVM also checks that each constructor begins with an invocation of a
constructor in the superclass.

Only "sort of." It's fairly easy to get an arbitrary
amount of code executed *before* the superclass' constructor
runs, as in

class Counterexample extends HasBoolConstructor {
Counterexample() {
super(boolMethod());
}

private bool boolMethod() {
// Twelve SQL queries,
// Eleven XML parses,
// Ten external programs,
// Nine RMI calls,
// Eight LDAP queries,
// Seven serializations,
// Six caught exceptions,
// Five di-a-logs!
// Four URLs,
// Three GC's,
// Two JAR downloads, and
return pearTree.add("Partridge");
}

private static final HashSet<String> pearTree =
The point is that the constructor gets hold of the new object (under the
name of 'this') before anyone else. Therefore, it is up to that constructor
to initialize fields as it sees fit. But nothing prevents the constructor
itself from showing the not-yet-initialized instance to whatever code it
wishes. What Java ensures is that the constructor _can_ keep things
tidy and protected from external interference; but it does not prevent the
constructor from being as untidy as it sees fit.

Right you are.
 
L

Lew

Eric said:
It's fairly easy to get an arbitrary
amount of code executed *before* the superclass' constructor
runs, as in

class Counterexample extends HasBoolConstructor {
Counterexample() {
super(boolMethod());
}

private bool boolMethod() {
// Twelve SQL queries,
// Eleven XML parses,
// Ten external programs,
// Nine RMI calls,
// Eight LDAP queries,
// Seven serializations,
// Six caught exceptions,
// Five di-a-logs!
// Four URLs,
// Three GC's,
// Two JAR downloads, and
return pearTree.add("Partridge");
}

private static final HashSet<String> pearTree =
new HashSet<String>();
}

In addition to the obvious dangers here that you've already discussed, the
instance-level access to a static structure is problematic. This is a
well-crafted example of code idioms to avoid.
 
R

Roedy Green

I am confused. My question is how can "this" reference be available in
a Java constructor ? After all, the current object ( to which "this"
refers to) has not been completely constructed yet, because we are
still in the constructor.

How are you to construct an object if you can't access its fields
before it is completely constructed?

You are implicitly accessing "this" when you say something like this:

MyClass( int x )
{
xx = x;
}

int xx;

That is equivalent to:

MyClass( int x )
{
this.xx = x;
}
--
Roedy Green Canadian Mind Products
http://mindprod.com

When your language is nowhere near Turing-complete, syntactic sugar can be your friend.
~ Eric S. Raymond (born: 1957-12-04 age: 51) The Cathedral and the Bazaar
 
D

Dave Searles

Eric said:
Thomas said:
According to Joshua Cranmer said:
The more technical answer:

When you construct an object with new Foo();, this is the bytecode
generated (roughly):

anew Foo
dup
invokespecial Foo#<init>()V
[the last reference on the stack you are free to do what you will with

Just for completeness: the JVM also verifies that whenever an object is
created (with the 'new' ocode) then a call to a constructor necessarily
follows, before any other use of the reference to the new instance. The
JVM also checks that each constructor begins with an invocation of a
constructor in the superclass.

Only "sort of." It's fairly easy to get an arbitrary
amount of code executed *before* the superclass' constructor
runs, as in

class Counterexample extends HasBoolConstructor {
Counterexample() {
super(boolMethod());
}

Does that compile? I seem to recall that using "this" before the
super-call is verboten, so boolMethod would have to be static here to be
callable here.
private bool boolMethod() {

But it isn't static.
// Twelve SQL queries,
// Eleven XML parses,
// Ten external programs,
// Nine RMI calls,
// Eight LDAP queries,
// Seven serializations,
// Six caught exceptions,
// Five di-a-logs!
// Four URLs,
// Three GC's,
// Two JAR downloads, and
return pearTree.add("Partridge");

It isn't even Hallowe'en yet. Lots of the local department/walmart/etc.
stores have jumped the gun, and now so have you. :)

Seriously, the overhyping of Christmas two or more months in advance is
liable to cause people to be sick of it before it even comes.

This also applies to the TV overhyping of the Olympics. They've been
advertising it nonstop for a year now and today I saw an ad blathering
about live coverage of something. The games don't start for a few months
yet -- so it must be live coverage of absolutely nothing in the way of
the meat-and-potatoes of the event. All this blitzing of the populace is
likely to accomplish is to ensure that much of the world's population is
sick of the Olympics before they even start.
 
E

Eric Sosman

Lew said:
Eric said:
It's fairly easy to get an arbitrary
amount of code executed *before* the superclass' constructor
runs, as in

class Counterexample extends HasBoolConstructor {
Counterexample() {
super(boolMethod());
}

private bool boolMethod() {
[...]
return pearTree.add("Partridge");
}

private static final HashSet<String> pearTree =
new HashSet<String>();
}

In addition to the obvious dangers here that you've already discussed,
the instance-level access to a static structure is problematic. This is
a well-crafted example of code idioms to avoid.

Okay, it was a whimsical example -- but maybe because of
whimsy I'm about to learn something I didn't know. Why is it
"problematic" to access a static element from non-static code?

class Problematic {
public void announce() {
System.out.println("Problematic?");
}
}
 
L

Lew

Eric said:
It's fairly easy to get an arbitrary
amount of code executed *before* the superclass' constructor
runs, as in
    class Counterexample extends HasBoolConstructor {
        Counterexample() {
            super(boolMethod());
        }
        private bool boolMethod() {
[...]
            return pearTree.add("Partridge");
        }
        private static final HashSet<String> pearTree =
            new HashSet<String>();
    }
In addition to the obvious dangers here that you've already discussed,
the instance-level access to a static structure is problematic.  This is
a well-crafted example of code idioms to avoid.

Eric said:
     Okay, it was a whimsical example -- but maybe because of
whimsy I'm about to learn something I didn't know.  Why is it
"problematic" to access a static element from non-static code?

That isn't what I said.
        class Problematic {
            public void announce() {
                System.out.println("Problematic?");
            }
        }

That's not the same at all. What I said is that "the access ... is
problematic", that is, the particular one under discussion, not just
any access.

The access to which I referred was an instance-level write to a static
memory structure. Your new example is a write to a stream, thus there
is no further state to observe. Apples and oranges.

In your first example the access is problematic because it isn't
thread safe. That is not true for your second example.
 
L

Lew

Lew said:
Eric said:
It's fairly easy to get an arbitrary
amount of code executed *before* the superclass' constructor
runs, as in
    class Counterexample extends HasBoolConstructor {
        Counterexample() {
            super(boolMethod());
        }
        private bool boolMethod() {
[...]
            return pearTree.add("Partridge");
        }
        private static final HashSet<String> pearTree =
            new HashSet<String>();
    }
That isn't what I said.
That's not the same at all.  What I said is that "the access ... is
problematic", that is, the particular one under discussion, not just
any access.
The access to which I referred was an instance-level write to a static
memory structure.  Your new example is a write to a stream, thus there
is no further state to observe.  Apples and oranges.

     System.out isn't static?  PrintStream has no observable state?
In your first example the access is problematic because it isn't
thread safe.  That is not true for your second example.

     Red herring.  Use Collections.synchronizedMap() on it if you like:
Now it's thread-safe, but still static.  What's "problematic?"

Nothing, any more. As I said, I was referring to the specific example
you published earlier. When you change the example, you fix the
problem. Let me repeat what I said for those who missed it - I was
not speaking in the general case. Stop putting words in my mouth, er,
keyboard.

So, to review - you posted an example that had a problematic aspect
with respect to threading. You then came back with two different
examples that did not have that problem, and about which I was NOT
speaking, and challenge me to find what's problematic about that. To
which I answer, nothing. So?

Different examples that don't have the problem are different in that
they don't have the problem. Duhhh.

Got it now?
 
E

Eric Sosman

Lew said:
[...]
So, to review - you posted an example that had a problematic aspect
with respect to threading.

... which you described as problematic without making
even the slightest reference to thread safety, but only to the
"instance-level access to a static structure" as the problematic
aspect.
You then came back with two different
examples that did not have that problem, and about which I was NOT
speaking, and challenge me to find what's problematic about that. To
which I answer, nothing. So?

I came back with ONE example that DID demonstrate exactly
what you'd pointed out as problematic, namely, "instance-level
access to a static structure." You then dragged in the matter
of thread safety, which serves only to cloud the issue, and I
showed how thread safety could be restored while still leaving
the ILATASS intact, and asked yet again why you found ILATASS
problematic.
Got it now?

Indeed, I do now see something I consider problematic.
 
L

Lew

Lew said:
[...]
So, to review - you posted an example that had a problematic aspect
with respect to threading.

Eric said:
     ... which you described as problematic without making
even the slightest reference to thread safety, but only to the
"instance-level access to a static structure" as the problematic
aspect.

Partly true. But again, and yet again, I point out that I said that
*that particular* use was problematic, not that instance-level access
to static structures in general is problematic. It is true that I did
not say why that particular use is problematic until you asked; that
was to let people figure it out. It is not true that I described
instance-level access as being the problematic aspect. What I said
precisely was, "the instance-level access to a static structure is
problematic." Not "any instance-level access", "the instance-level
access" in the context of your example.

When you questioned my assertion, I explained that I was speaking of
just that example. Now you've questioned that same point over and
over and over. All I can do is keep pointing out that I was speaking
only of *that particular access*.

This is now my third attempt to clarify that point. Please
discontinue your straw-man argumentativeness.

You are a major contributor to this newsgroup and your posts are
usually among the most informative here. I am distraught at your
sudden and inexplicable sinking into trollishness.

Eric said:
     I came back with ONE example that DID demonstrate exactly
what you'd pointed out as problematic, namely, "instance-level
access to a static structure."  You then dragged in the matter

Once again, I did not point that out as problematic in general. I
pointed out that that *particular* instance-level access to a static
structure was problematic. Your new example did not share what was
problematic about the first example, which I explained the first time
you asked. And the second. And the third. And I will just say for
the fourth and subsequent times you try to argue with me on this, that
I was speaking of the lack of thread safety in that one particular
example, which the other examples did not evince. Just refer to the
answers already given as you repeat and repeat and repeat your point.

How many times do you need me to explain what I meant?

Eric said:
of thread safety, which serves only to cloud the issue, and I
showed how thread safety could be restored while still leaving
the ILATASS intact, and asked yet again why you found ILATASS
problematic.

When you fix the problematic aspect the problem goes away. Duhhh,.

You may recall (or maybe you don't) that when you asked "yet again"
why I found the "ILATASS" problematic that I explained that I only
found the one example to have that problem, and that the other two
examples, including the one with thread safety restored, not to be
problematic. So the answer, already stated and here repeated, is that
I do NOT find the thread-safe version problematic.

Why do you ignore my answers and repeat your question?
 

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
474,262
Messages
2,571,050
Members
48,769
Latest member
Clifft

Latest Threads

Top