[...]
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'?)