Re: exception inside constructors and finalize



On Thu, 2005-04-28 at 12:54 +0000, Patricia Shanahan wrote:
> Ross Bamford wrote:
>
> ...
> > An exception handled within a constructor is a regular exception, but
> > one thrown by a constructor *should* result in the object not being
> > allocated, or deallocated immediately. It *always* leaves the object in
> > an undefined state (Null in my experience but don't rely on it)
> >
> > For example the following code:
> >
> > public class Test
> > {
> > public String tester;
> >
> > public Test() throws Exception
> > {
> > tester = "Tester object";
> > throw(new Exception());
> > }
> >
> > public static void main(String args[])
> > {
> > Test t = null;
> > try {
> > t = new Test();
> > } catch (Exception e) { /* ignore */ }
> >
> > String s = (t == null) ? "Null object" : t.tester;
> > System.out.println(s);
> > }
> > }
> >
> > produces the output "Null object", unless we remove the throws clause
> > from the constructor (when it's "Tester object" obviously).
>
> I agree generally with your comments, but I don't think you
> got this one quite right.
>
> t is null because you initialized it to null, and nothing
> changed it between initialization and the null test. You can
> count on an assignment not happening if evaluation of its
> right hand side completes abruptly.
>
> Memory for the object is allocated, and any initialization
> that happens before the exception gets done. Whether the
> object is immediately eligible for garbage collection
> depends, as always, on its reachability.
>
> Here's a variation of your program that demonstrates this.
>
> public class ConstructorTest
> {
> static ConstructorTest lastConstructed = null;
> public String tester;
>
> public ConstructorTest() throws Exception
> {
> lastConstructed = this;
> tester = "ConstructorTest object";
> throw(new Exception());
> }
>
> public String toString()
> {
> return tester;
> }
>
> public static void main(String args[])
> {
> Object t = "Not a ConstructorTest object";
> try {
> t = new ConstructorTest();
> } catch (Exception e) { /* ignore */ }
>
> String s = (t == null) ? "Null object" : t.toString();
> System.out.println(s);
> if(lastConstructed != null)
> {
> System.out.println(lastConstructed);
> }
> }
> }
>
> It prints:
>
> Not a ConstructorTest object
> ConstructorTest object
>
> Patricia
>

That surprised me to begin with, but now I think more on it I realise
it's absolutely the only way it could work - I was falling into the
"Exceptions are special" trap myself there I think, or maybe
thinking++ :)

I guess from the day-to-day programmer perspective, it doesn't really
matter unless you're keeping extra references like above, the effect is
the same (?), but then it's one of those situations where you innocently
do keep a reference one time and end up chasing the same bug for days ;)

I'll filter out the dumb posts in future before they get out ;>

Cheer,
Ross

--
[Ross A. Bamford] [ross AT the.website.domain]
Roscopeco Open Tech ++ Open Source + Java + Apache + CMF
http://www.roscopec0.f9.co.uk/ + info@xxxxxxxxxxxxxxxxxx


.