From: Jim Janney on 26 May 2010 11:32 Alan Malloy <alan.NO.SPAM(a)malloys.org> writes: > Jim Janney wrote: >> Tom Anderson <twic(a)urchin.earth.li> writes: >> >>> On Tue, 25 May 2010, Patricia Shanahan wrote: >>> >>>> Rhino wrote: >>>>> I've received some criticism recently with regards to the approach >>>>> I use to initializing variables so I'd like to throw this issue out >>>>> to the whole group so that I can learn more about the pros and cons >>>>> of the approach I am using.... >>>>> >>>>> Basically, I initialize pretty much every variable as I declare it, >>>>> just to be sure it has some kind of value right away. That initial >>>>> value is typically a zero for a number or a null for an >>>>> object. Some recent criticism questioned this practice so I thought >>>>> I'd review some of the material that helped get me in that habit in >>>>> the first place. >>>> ... >>>> >>>> I follow the extreme opposite view. I initialize a local variable at the >>>> point of declaration if doing so makes logical sense or I know that I >>>> know something the compiler does not know. Generally, that involves the >>>> compiler assuming a fall-through from a call to System.exit. >>>> >>>> The reason for doing this is simple. I make mistakes. I have done most >>>> of my work in environments in which pair programming is not feasible, so >>>> I cannot depend on another programmer to catch my mistakes. To the >>>> maximum extent possible, I want to co-opt Eclipse's continuous source >>>> code checking as an aid to finding my mistakes as quickly as possible. >>>> >>>> One mistake I might make is omitting a logically necessary assignment to >>>> a local variable. Routinely initializing at the point of declaration >>>> would eliminate the possibility that it might be detected by the compiler. >>>> >>>> When I get a definite assignment error I take the time to look at my >>>> logic. Just occasionally, simply adding an initializer to the >>>> declaration would leave either an actual error or unnecessarily >>>> convoluted code, and I do something else. >>> This is exactly what i do. By initialising locals at the point of >>> definition, you immediately throw away the compiler's ability to >>> sanity-check your assignments to them. Don't do that. >> >> You've lost me here. We all make mistakes, but I don't see how this >> is supposed to help. Perhaps someone could post a short example? >> > > void printList(MyLinkedList list) { > MyNode n = null; > // Some other initialization code > > // forgot to uncomment the next line > // n = list.first(); > > while (n != null) { > print(n); > n = n.next(); > } > } > > Without the initial null assignment, the compiler will let you know > you've made a mistake. Putting it there destroys the read-before-use > checking and causes the method to do nothing at runtime, with no error > detection at all. OIC, thanks. -- Jim Janney
From: Tom Anderson on 26 May 2010 14:59 On Wed, 26 May 2010, Gunter Herrmann wrote: > Tom Anderson wrote: >> On Tue, 25 May 2010, Arne Vajh?j wrote: > >>> But I would note that in many cases the optimal solution is to >>> wait declaring the variable until you have a value to give it. >> >> Absolutely. Goes without saying! > > There are exceptions to this rule (pun intended) > > Foo foo = null; > > try { > foo = new Foo(); > foo.doProcessing(); > } > catch (FooException ex) { > doSomething(ex); > } > finally { > foo.cleanup(); > } > > In this case you have to initialize the variable foo. No, because you should just write it like this: Foo foo = new Foo(); try { foo.doProcessing(); } catch (FooException ex) { doSomething(ex); } finally { foo.cleanup(); } If new Foo() can also throw an exception, then wrap that whole lot in a try-catch or whatever. tom -- Please! Undo clips before opening handle.
From: Tom Anderson on 26 May 2010 15:06 On Tue, 25 May 2010, Lew wrote: > Arne Vajh?j wrote: >>>>>> I strongly favor readability here. The extra overhead of something >>>>>> getting initialized twice should be minimal or zero if the JIT >>>>>> compiler optimizes it away. > > Lew wrote: >>>>> Minimal, perhaps, but the system is not permitted to optimize away >>>>> member initialization. > > Arne Vajh?j wrote: >>>> What would prevent the JIT compiler from optimizing the setting of >>>> an int to zero twice to only doing it once? > > Lew wrote: >>> The JLS, section 12.5, "Creation of New Class Instances": >>> "In some early implementations, the compiler incorrectly omitted the >>> code to initialize a field if the field initializer expression was a >>> constant expression whose value was equal to the default initialization >>> value for its type." > > Arne Vajh?j wrote: >> But isn't that talking about javac and not JIT? > > Not as I read it, but maybe it is. > > Regardless, JIT requires multiple executions (by default 10,000 IIRC) > before it decides to optimize something. By definition, initialization > code is run once. Um, once per instance. If it's an instance initializer. Which is what i thought we were talking about here. That could easily be run 10 000 times in a single program. > Regardless, as you pointed out and I reiterated, the performance impact is > not enough to trump issues of readability or self-documentation. Nor is it > required to initialize member variables to their default values. > > I admit it's possible that I read this wrong, but I think not. I don't see how a statement like that is even meaningful when applied to a JVM. You can require that a JVM behaves *as if* it does or doesn't do something, defined in terms of some model of what the JVM is doing, but as long as it does, it can do it however it likes. I don't see how rules to the contrary would be useful or even possible to judge compliance to. tom -- uk.local groups TO BE RENAMED uk.lunatic.fringe groups
From: Eric Sosman on 26 May 2010 15:53 On 5/26/2010 3:06 PM, Tom Anderson wrote: > On Tue, 25 May 2010, Lew wrote: > >> Arne Vajh?j wrote: >>>>>>> I strongly favor readability here. The extra overhead of something >>>>>>> getting initialized twice should be minimal or zero if the JIT >>>>>>> compiler optimizes it away. >> >> Lew wrote: >>>>>> Minimal, perhaps, but the system is not permitted to optimize away >>>>>> member initialization. >> >> Arne Vajh?j wrote: >>>>> What would prevent the JIT compiler from optimizing the setting of >>>>> an int to zero twice to only doing it once? >> >> Lew wrote: >>>> The JLS, section 12.5, "Creation of New Class Instances": >>>> "In some early implementations, the compiler incorrectly omitted the >>>> code to initialize a field if the field initializer expression was a >>>> constant expression whose value was equal to the default initialization >>>> value for its type." >> >> Arne Vajh?j wrote: >>> But isn't that talking about javac and not JIT? >> >> Not as I read it, but maybe it is. >> >> Regardless, JIT requires multiple executions (by default 10,000 IIRC) >> before it decides to optimize something. By definition, initialization >> code is run once. > > Um, once per instance. If it's an instance initializer. Which is what i > thought we were talking about here. That could easily be run 10 000 > times in a single program. > >> Regardless, as you pointed out and I reiterated, the performance >> impact is not enough to trump issues of readability or >> self-documentation. Nor is it required to initialize member variables >> to their default values. >> >> I admit it's possible that I read this wrong, but I think not. > > I don't see how a statement like that is even meaningful when applied to > a JVM. You can require that a JVM behaves *as if* it does or doesn't do > something, defined in terms of some model of what the JVM is doing, but > as long as it does, it can do it however it likes. I don't see how rules > to the contrary would be useful or even possible to judge compliance to. A suppressed initialization can be observed: class Super { Super() { evilCode(); } void evilCode() { } } class Sub extends Super { int value = 0; // suppressible? Sub() { System.out.println("value = " + value); } void evilCode() { value = 42; } public void main(String[] unused) { new Sub(); } } Yes, this is evil code that merits severe chastisement of its author, but despite its sins it is perfectly legal Java -- and the required output is "value = 0". If the initialization were suppressed, the output would be "value = 42" -- and that would (was?) wrong. -- Eric Sosman esosman(a)ieee-dot-org.invalid
From: Tom Anderson on 26 May 2010 17:27
On Wed, 26 May 2010, Tom Anderson wrote: > On Wed, 26 May 2010, Gunter Herrmann wrote: > >> Tom Anderson wrote: >>> On Tue, 25 May 2010, Arne Vajh?j wrote: >> >>>> But I would note that in many cases the optimal solution is to >>>> wait declaring the variable until you have a value to give it. >>> >>> Absolutely. Goes without saying! >> >> There are exceptions to this rule (pun intended) >> >> Foo foo = null; >> >> try { >> foo = new Foo(); >> foo.doProcessing(); >> } >> catch (FooException ex) { >> doSomething(ex); >> } >> finally { >> foo.cleanup(); >> } >> >> In this case you have to initialize the variable foo. > > No, because you should just write it like this: > > Foo foo = new Foo(); > try { > foo.doProcessing(); > } > catch (FooException ex) { > doSomething(ex); > } > finally { > foo.cleanup(); > } > > If new Foo() can also throw an exception, then wrap that whole lot in a > try-catch or whatever. If the handling for FooExceptions from the constructor and the processing is the same: try { Foo foo = new Foo(); try { foo.doProcessing(); } finally { foo.cleanup(); } } catch (FooException ex) [ doSomething(ex); } tom -- unconstrained by any considerations of humanity or decency |