Prev: Basic JUnit questions
Next: Discount CHLOE True leather AAA Wholesale (www.supertradeonline06.com )
From: Eric Sosman on 21 Mar 2010 09:32 On 3/20/2010 6:48 PM, Rhino wrote: > On Mar 20, 4:53 pm, Eric Sosman<esos...(a)ieee-dot-org.invalid> wrote: >> [...] >> 5) Refrain from calling non-final instance methods on objects >> that haven't finished construction! This is a Big No-No; >> don't do it! > [...] > With regards to your fifth point, I'm afraid I still get a little > muddled when someone makes a generalized commment like that without > also pointing to the specific thing I've done wrong. Can you clarify > which object hasn't finished construction? Think, Rhino, think! Think about the life cycle of an object instance! Do you remember the sequence of events? 1) The JVM allocates memory for the object's fields and clears it all to zero (actually, the moment at which the zeroing occurs isn't specified, but it happens somewhere before Step 2) 2) The JVM calls the object's constructor, which calls its superclass constructor, ..., which calls the constructor of java.lang.Object. 4) The Object constructor initializes the Object aspects of the new memory, then returns to the next constructor which initializes the Whatnot aspects, then returns ..., to the class' own constructor, which initializes the MostSpecific aspects of the object. 5) The most specific constructor returns, and *now* at last the construction of the object is complete. Now, can you spot any moment in this scenario where the object exists (sort of) but has not been fully constructed? Can you say what code is running at that moment? Does this narrow your search any? Answer: Gur GrfgUbhe bowrpg unf abg orra pbafgehpgrq hagvy gur GrfgUbhe pbafgehpgbe ergheaf (abg rira gura, vs vg'f npghnyyl n GrfgUbhe fhopynff gung'f haqre pbafgehpgvba). Lrg gur GrfgUbhe pbafgehpgbe pnyyf bireevqnoyr vafgnapr zrgubqf. Frr Oybpu "Rssrpgvir Wnin," Vgrz 15. -- Eric Sosman esosman(a)ieee-dot-org.invalid
From: Lew on 21 Mar 2010 13:05 Rhino wrote: > That all makes sense. And it's a good lesson to me too. Sometimes, I > see code in examples in the newsgroup or elsewhere online and imitate > them without fully understanding what they are doing. I think I must > have seen something like: > > new TestHour(); > > used in a fragment once, noticed that it was more concise than: > > TestHour testHour = new TestHour(); > > and saw that the former was more concise than the latter, and just > assumed it was exactly equivalent. That assumption turns out to be > wrong as I've learned in this thread and now I know why. I can stay > away from that approach and modify any other code that does that in > "real" programs, as opposed to SSCCEs. The only difference between the two is that the first discards the reference and the second assigns it to a variable. If one does not need to reuse the reference, the first form is fine: new TestHour().doSomething(); If one needs to reuse the reference, the second form is required: TestHour testHour = new TestHour(); testHour.doSomething(); testHour.doSomethingElse(); -- Lew
From: Lew on 21 Mar 2010 13:13 Eric Sosman wrote: > Answer: Gur GrfgUbhe bowrpg unf abg orra pbafgehpgrq hagvy > gur GrfgUbhe pbafgehpgbe ergheaf (abg rira gura, vs vg'f npghnyyl > n GrfgUbhe fhopynff gung'f haqre pbafgehpgvba). Lrg gur GrfgUbhe In a manner of speaking, the 'TestHour' object *has* been completely constructed after its completion, even if part of a subclass's construction. It's the subclass instance that has not been completely constructed. To be more precise, it's the 'TestHour' part of the overall object that has been completely constructed when the 'TestHour' part of construction completes. > pbafgehpgbe pnyyf bireevqnoyr vafgnapr zrgubqf. Frr Oybpu > "Rssrpgvir Wnin," Vgrz 15. -- Lew
From: Eric Sosman on 21 Mar 2010 15:38 On 3/21/2010 1:13 PM, Lew wrote: > Eric Sosman wrote: >> Answer: Gur GrfgUbhe bowrpg unf abg orra pbafgehpgrq hagvy >> gur GrfgUbhe pbafgehpgbe ergheaf (abg rira gura, vs vg'f npghnyyl >> n GrfgUbhe fhopynff gung'f haqre pbafgehpgvba). Lrg gur GrfgUbhe > > In a manner of speaking, the 'TestHour' object *has* been completely > constructed after its completion, even if part of a subclass's > construction. It's the subclass instance that has not been completely > constructed. ... except that if a subclass is being constructed, the object is not fully constructed when a superclass constructor finishes. The object is a SubTestHour, which "is a" TestHour only in the sense that it can stand in for a TestHour in any code that wants to use a TestHour. Still, the .getClass() method returns SubTestHour.class, not TestHour.class. > To be more precise, it's the 'TestHour' part of the overall object that > has been completely constructed when the 'TestHour' part of construction > completes. ... and if the TestHour constructor calls an overridable method, and SubTestHour overrides that method, what is the status of the SubTestHour object when the method is called from TestHour's constructor, hmmm? class Super { private final int value; Super() { value = 42; showValue(); // DON'T DO THIS!!! } void showValue() { System.out.println("Super value = " + value); } public static void main(String[] unused) { new Sub(); } } class Sub extends Super { private final String value; Sub() { value = "forty-two"; showValue(); // DON'T DO THIS!!! } void showValue() { System.out.println("Sub value = " + value); } } (If you don't see what's wrong, do two things: First, predict the output, and second, compile and run the code.) -- Eric Sosman esosman(a)ieee-dot-org.invalid
From: Lew on 21 Mar 2010 15:54
Eric Sosman wrote: >>> Answer: Gur GrfgUbhe bowrpg unf abg orra pbafgehpgrq hagvy >>> gur GrfgUbhe pbafgehpgbe ergheaf (abg rira gura, vs vg'f npghnyyl >>> n GrfgUbhe fhopynff gung'f haqre pbafgehpgvba). Lrg gur GrfgUbhe Lew wrote: >> In a manner of speaking, the 'TestHour' object *has* been completely >> constructed after its completion, even if part of a subclass's >> construction. It's the subclass instance that has not been completely >> constructed. Eric Sosman wrote: > ... except that if a subclass is being constructed, the object > is not fully constructed when a superclass constructor finishes. "The object" being the subclass instance. I was discussing only that *portion* of the object for which the superclass constructor is responsible, hence the "in a manner of speaking". > The object is a SubTestHour, which "is a" TestHour only in the sense > that it can stand in for a TestHour in any code that wants to use > a TestHour. Still, the .getClass() method returns SubTestHour.class, > not TestHour.class. Lew wrote: >> To be more precise, it's the 'TestHour' part of the overall object that >> has been completely constructed when the 'TestHour' part of construction >> completes. Eric Sosman wrote: > ... and if the TestHour constructor calls an overridable method, > and SubTestHour overrides that method, what is the status of the > SubTestHour object when the method is called from TestHour's > constructor, hmmm? Indeed, that is the danger in calling overridable methods before the constructor (in this case, the superclass constructor) is finished. > class Super { > private final int value; > Super() { > value = 42; > showValue(); // DON'T DO THIS!!! At this point, the 'Super' part of any subclass instance is not yet fully constructed. > } > void showValue() { > System.out.println("Super value = " + value); > } > public static void main(String[] unused) { > new Sub(); > } > } > > class Sub extends Super { > private final String value; > Sub() { > value = "forty-two"; > showValue(); // DON'T DO THIS!!! > } > void showValue() { > System.out.println("Sub value = " + value); > } > } > > (If you don't see what's wrong, do two things: First, > predict the output, and second, compile and run the code.) Excellent exegesis, Eric. Regardless of "manner of speaking", it is dangerous to use an instance before it's fully constructed, super, sub and barrel. -- Lew |