Reputation: 1095
If the constructor ends up with an exception, is the object created exactly the same with a normal one?
class A {
static A o;
A() throws Exception {
o=this;
throw new Exception();
}
void f() { System.out.println("f(): entry."); };
static public void main(String[]args ) {
try {
A o =new A();
}
catch (Exception e) {
System.out.println("Exception: " + e);
}
A.o.f(); // Is it safe to use this object?
}
}
This compiles and runs, and the output of this program is:
Exception: java.lang.Exception
f(): entry.
Upvotes: 3
Views: 137
Reputation: 120506
A.o.f(); // Is it safe to use this object?
It is a regular java object that will respond to method calls just as any other Java object. This is not a source of undefined behavior as far as the Java language is concerned.
That doesn't mean it's safe to use. Many classes' safety depends on their ability to maintain important invariants, and unexpected exceptions thrown during construction or critical operations often mean that those invariants do not hold so they are not safe to use.
Consider what happens if you subclass A
public class S extends A {
boolean dirty;
S() throws Exception {
// Do work to maintain important security invariants.
dirty = true;
}
void foo() {
if (dirty) {
System.out.println("clean");
dirty = false;
}
System.out.println("foo");
}
public static void main(String... argv) {
try {
new S();
} catch (Exception ex) {}
// Now A.o is an instance of S, but S's constructor
// was never called.
S s = (S) A.o; // works.
s.foo(); // Never prints clean before printing foo.
}
}
Upvotes: 2
Reputation: 47729
If you catch the exception, the constructed object is never passed back to the caller, and the caller's result variable is not set. However, the static variable would, in theory, be set, and I can't see any reason why it would not be accessible.
Note, however, that method verification will not allow you to store this
until after the super
constructor is called, so this is not a "back door" into otherwise protected objects.
Since it's your object, "safe" is up to you.
[A little more detail: When the compiled version of your constructor is entered, the "raw" Java object is fully constructed -- no additional work is needed by the system to make it valid. The super
constructor has not been called yet, however, and it's either up to you to explicitly make a super
call or have the compiler insert the super
call by default (which it will do at the start of the method if you don't have an explicit call). The "bytecode verifier" in the JVM has some very strict rules about what can happen in a constructor prior to calling the super
constructor, and storing this
to a static would be a definite no-no -- you'd get a VerifyError.]
Upvotes: 3