From: Lew on 26 May 2010 18:28 Tom Anderson wrote: >> 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); > } > Beautiful idioms. A third, uglier but formally correct idiom is: final Foo resource; try { resource = new Foo(); } catch ( FooException ex ) { log( ex ); return; } assert resource != null; try { resource.process(); } catch ( FooException ex ) { log( ex ); } finally { resource.cleanup(); } -- Lew
From: Arne Vajhøj on 26 May 2010 20:21 On 25-05-2010 22:27, 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. Unless it is static then it will be run once per instantiation. That could be many times. Arne
From: Arne Vajhøj on 26 May 2010 20:25 On 26-05-2010 11:28, 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. True. But you should test for null before calling cleanup to handle the case where the Foo constructor throws FooException. Arne
From: Arne Vajhøj on 26 May 2010 20:27 On 26-05-2010 14:59, 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. But in that case the improvement is so so. Arne
From: RedGrittyBrick on 27 May 2010 05:01
On 26/05/2010 23:28, Lew wrote: > Tom Anderson wrote: >>> 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); >> } >> > > Beautiful idioms. > > A third, uglier but formally correct idiom is: > > final Foo resource; > try > { > resource = new Foo(); > } > catch ( FooException ex ) > { > log( ex ); > return; > } > assert resource != null; > try > { > resource.process(); > } > catch ( FooException ex ) > { > log( ex ); > } > finally > { > resource.cleanup(); > } > I'm always a little uncomfortable when the exception handling overwhelms and obscures the business logic: new Foo().process().cleanup(); // <stimpy>Sigh!</stimpy> The point of the exception handling mechanism is to separate error handling code from business logic code. Sometimes it is hard to achieve this. -- RGB |