Ander Juaristi
Ander Juaristi

Reputation: 328

Throwing an exception through a constructor

Suppose I have the following piece of code:

public class Conf{    
  public Conf(String szPath) throws IOException, ConfErrorException{
      ...
  }
  public void someMethod(){
    ...
  }
}

Then I want to instantiate the object this way:

Conf configuration = new Conf("/etc/myapp/myconf.conf");

If, for some reason, the constructor throws any of the exceptions defined, will the object be created?
I mean, will I still be able to access the methods in it, for example, like in the following code?

Conf configuration;
try{
   configuration = new Conf("/etc/myapp/myconf.conf");
}catch(IOException|ConfErrorException e){
   //Suppose we entered here
   configuration.someMethod();
}

Upvotes: 2

Views: 5063

Answers (8)

Edwin Dalorzo
Edwin Dalorzo

Reputation: 78579

Let me start with an scenario of failing object construction that can exemplify what could go wrong if you could use such failed object:

Let's define a class A, such that:

class A {
   private String a = "A";

   public A() throws Exception {
        throw new Exception();
   }
}

Now, let's assume we would like to create an object of type A in a try...catch block.

A a = null;
try{
  a = new A();
}catch(Exception e) {
  //...
}
System.out.println(a);

Evidently, the output of this code will be: null.

Why Java does not return a partially constructed version of A? After all, by the point the constructor fails its name field member has already being initialized, right?

Java does not do that because the object was not successfully built. The object is in a inconsistent state, and it is therefore discarded by Java. Your variable A is not even initialized, it is kept as null.

Now, as you know, to fully build a new object, all its super classes must be initialized first. If one of the super classes failed to build, what would be the final state of the object? It is impossible to determine that.

Look at this more elaborate example

class A {
   private final int a;
   public A() throws Exception { 
      a = 10;
   }
}

class B extends A {
   private final int b;
   public B() throws Exception {
       methodThatThrowsException(); 
       b = 20;
   }
}

class C extends B {
   public C() throws Exception { super(); }
}

When the constructor of C is invoked, if an exception occurs on initializing B, what would be the value of the final variable int b?

As such, the object C cannot be created, it is bogus, it is trash, it is not fully initialized.

Upvotes: 6

Jonathan
Jonathan

Reputation: 20375

An object will be created but you will never receive a reference to it. As it stands, your code would never compile:

Conf configuration;
try{
    configuration = new Conf("/etc/myapp/myconf.conf");
}catch(IOException|ConfErrorException e){
    //Suppose we entered here
   configuration.someMethod();
}

The compiler recognises that configuration may not be initialised when it gets to the catch-block.

Upvotes: 1

Dmitry Zaytsev
Dmitry Zaytsev

Reputation: 23952

Conf configuration = new Conf("/etc/myapp/myconf.conf");

This code completes in 3 steps:

  1. Create all base objects.
  2. Create object Conf
  3. Assign reference to configuration

Since you are not completed the second step, the second step won't complete also, which means that configuration won't be initialized. Which means that configuration is not null, it's not even initialized. Your code will not compile.

However since first step is completed, there will be a bunch of lost object (eligible for GC).

Upvotes: 2

Peter Lawrey
Peter Lawrey

Reputation: 533432

the constructor throws any of the exceptions defined, will the object be created?

The object is always created before the constructor is called. Otherwise there would be no this object in the constructor to initialise.

If you throw an Exception, you will lose a reference to that object, unless you have done something suspect like store the object in the constructor before throwing an exception.

public class Main {
    static class ThrowsException {
        static final List<ThrowsException> BAD_LIST = new ArrayList<>();

        ThrowsException() {
            System.out.println("this = " + this);
            BAD_LIST.add(this);
            throw new RuntimeException();
        }
    }

    public static void main(String... args) {
        for (int i = 0; i < 3; i++) {
            ThrowsException te = null;
            try {
                te = new ThrowsException();
            } catch (Exception ignored) {
            }
            System.out.println("te = " + te);
        }
        System.out.println(ThrowsException.BAD_LIST);
    }

prints

this = Main$ThrowsException@22911fb5
te = null
this = Main$ThrowsException@65b8b5cd
te = null
this = Main$ThrowsException@41a7d9e7
te = null
[Main$ThrowsException@22911fb5, Main$ThrowsException@65b8b5cd, Main$ThrowsException@41a7d9e7]

Upvotes: 6

Liping Huang
Liping Huang

Reputation: 4476

No, if there is a exception is thrown when initialize the object, the object will not be created.

Upvotes: -1

Hazhir
Hazhir

Reputation: 788

No, if the constructor of an object throws an exception you wont get the object's instance.

it's one of the "best" methods for singleton objects that should not get created by constructor.

Upvotes: 0

Patricia Shanahan
Patricia Shanahan

Reputation: 26175

No, a throw of an exception from the constructor completes the try block abruptly. Nothing is returned from the constructor. Nothing more in the block runs. That means, in your code, configuration is unchanged.

Upvotes: 2

Azodious
Azodious

Reputation: 13872

If, for some reason, the constructor throws any of the exceptions defined, will the object be created?

No. If constructor throws exception, reference configuration will be assigned no value.

Refer this: What conditions cause object instantiation to return null?

Upvotes: 0

Related Questions