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
the constructor.
gregorie. | Essex, UK