Path: csiph.com!usenet.pasdenom.info!gegeweb.org!eternal-september.org!feeder.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Martin Gregorie Newsgroups: comp.lang.java.programmer Subject: Re: Interface with implied Constructor Date: Sat, 20 Jul 2013 21:18:31 +0000 (UTC) Organization: A noiseless patient Spider Lines: 123 Message-ID: References: <925adeb1-65b5-4a50-86a8-4f04784f8da0@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Injection-Date: Sat, 20 Jul 2013 21:18:31 +0000 (UTC) Injection-Info: mx05.eternal-september.org; posting-host="e5160e2be48f1ea550cf61512446f525"; logging-data="2579"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18Q2XrBLw8I+9PBQ8nXfSuR1Owhm98ROLY=" User-Agent: Pan/0.139 (Sexual Chocolate; GIT bf56508 git://git.gnome.org/pan2) Cancel-Lock: sha1:jfoEP6oH/GjxqAK8Po/d1vPnDb0= Xref: csiph.com comp.lang.java.programmer:24785 On Sat, 20 Jul 2013 17:12:47 -0400, Eric Sosman wrote: > On 7/20/2013 3:12 PM, Martin Gregorie wrote: >> On Sat, 20 Jul 2013 19:46:16 +0200, Robert Klemme wrote: >> >>> On 19.07.2013 23:21, Martin Gregorie wrote: >>>> [...] >>>> I take the opposite approach to Robert over that for one reason: that >>>> the only way to report init errors in a constructor is to throw an >>>> Exception, >>>> which means the instance declaration often needs to go inside a >>>> try/catch block which can screw up scoping. >>> >>> In what ways does this screw up scoping? >>> >> Just that I often find that I need access to the instance outside the >> try/ >> catch block containing the constructor call and I don't much like >> initialising the pointer as null. > > Then ... don't initialize it. > > Thing thing; > try { > thing = new Thing(); > } catch (DooWopDooWopDooWopException ex) { > logger.log(Level.SEVERE, "Eek!", ex); > throw ex; > } > System.out.println(thing.getSwing()); > ... > > This form has the advantage that the compiler will complain if the > all-important `throw ex;' is forgotten, whereas initializing to null > would just get you an NPE. > > Very occasionally there's a situation where you really do need > to use the null-ness of `thing' as an indication that construction > failed. In that case, I'd still suggest not initializing: > > Thing thing; > try { > thing = new Thing(); > } catch (DooWopDooWopDooWopException ex) { > logger.log(Level.SEVERE, "Eek!", ex); > thing = null; > } > if (thing != null) { > System.out.println(thing.getSwing()); > else { > System.out.println("It don't mean a thing"); > } > > IMHO, situations like this are suggestive of a poorly-designed Thing > class (which you may be forced to endure), or of a method that's trying > to do too many things and might better be split up. > >> This is a result of my dislike of using Exceptions to signal anything >> except a fatal error and may well be a hangover from writing a lot of C >> in the past. A method that returns reference to a library class whose >> constructor can throw an exception, e.g. Integer, but does not itself >> return an exception requires this sort of structure: >> >> public class Altitude { >> int alt = 0; >> String error = null; >> >> /** >> * Returning a negative number indicates an invalid height. >> */ >> public int getHeight(String height) >> { >> Integer h = null; > > Since this initialization is useless (the variable will > always be overwritten, exception or no), why even have it? > >> try { >> h = new Integer(height); >> if (h < 0) >> error = "Below MSL"; >> } >> catch (NumberFormatException e) >> { >> error = e.getMessage(); h = new Integer(-1); >> } >> >> return alt = h.intValue(); >> } >> >> public boolean isValid() >> { return error === null; } >> >> public String getError() >> { return error; } >> } >> >> This isn't a really good example because Integer provides other ways of >> doing the job, but it does illustrate the sort of scoping problem I'm >> talking about: that of allowing access to the Integer instance in both >> parts of the try/catch block as well as from surrounding parts of the >> method body. > > I don't see how the NumberFormatException has much to do > with it: Your getHeight() method needs the `h' at the point of its > return, so its scope must include the return statement. The only > "scoping issue" I can see is that the try block and the catch block have > their own subsidiary scopes in which `h' also needs to be (and is) > visible -- but then, why aren't you worried about the scope of `height'? > (Or even of `error' and `alt'?) > You're right, of course. But, please bear in mind that I concocted this example at Robert's request to illustrate the sort of scoping situation where I prefer to use a constructor that never throws an Exception plus an init() method that can throw one rather than a constructor that does it all but needs to throw an Exception if a recoverable error occurs in the constructor. -- martin@ | Martin Gregorie gregorie. | Essex, UK org |