Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it not allowed to throw an exception in a Java instance initialization block?

Tags:

java

When I try to throw an exception in an instance initialization (not class initialization) block I get the error:

initializer must be able to complete normally

Why is it not allowed although Java does it itself?

The following example creates four classes. The class A fails during instantiation because of an ArithmeticException. This can be and handled with a catch. The same for B which fails with a NullPointerException. But when I try to throw a NullPointerException on my own as in C the program does not compile. And I get the same error when I try to define my own RuntimeException as in D. So:

How can I do the same as Java does itself?

// -*- compile-command: "javac expr.java && java expr"; -*-

class expr
{
    class A
    {
        int y;
        {{ y = 0 / 0; }}
    }

    class B
    {
        Integer x = null;
        int y;
        {{ y = x.intValue(); }}
    }

    class C
    {
        {{ throw new NullPointerException(); }}
    }

    class Rex extends RuntimeException {}

    class D
    {
        {{ throw new Rex(); }}
    }

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

        try { B b = new B(); }
        catch (Exception e) { System.out.println (e); }

        try { C c = new C(); }
        catch (Exception e) { System.out.println (e); }

        try { D d = new D(); }
        catch (Exception e) { System.out.println (e); }
    }

    public static void main (String argv[])
    {
        expr e = new expr();
        e.run();
    }
}
like image 354
ceving Avatar asked Nov 23 '12 16:11

ceving


People also ask

What will happen if a runtime exception is thrown from a static initialization block?

A static block can throw only a RunTimeException, or there should be a try and catch block to catch a checked exception. A static block occurs when a class is loaded by a class loader.

Can we throw exception from TRY block in Java?

Java try block is used to enclose the code that might throw an exception. It must be used within the method. If an exception occurs at the particular statement in the try block, the rest of the block code will not execute. So, it is recommended not to keep the code in try block that will not throw an exception.

What is the use of instance initialization block in Java?

Instance Initialization Blocks or IIB are used to initialize instance variables . So firstly, constructor is invoked and the java compiler copies the instance initializer block in the constructor after the first statement super(). They run each time when object of the class is created.

Can we throw an unchecked exception from a static block in Java?

You cannot use throws keyword with a static block, and more over a static block is invoked at compile time (at the time of class loading) no method invokes it.


2 Answers

{ throw new Rex(); }

That means that the instance will be never initialized properly. There should be some condition where the instance can be initialized properly. e.g.

{ if(true) { throw new Rex(); } } //It doesn't complain here

If the exception being thrown is a checked-exception then you must add it to the constructor's throws clause. e.g.

public class MyObject {
    { 
        //...
            throw new Exception();
        //...
    }

    public MyObject() throws Exception {

    }
}
like image 145
Bhesh Gurung Avatar answered Oct 11 '22 12:10

Bhesh Gurung


initializer must be able to complete normally

means that there must be a possible code path that doesn't throw an exception. Your examples unconditionally throw, and are therefore rejected. In the other examples, the static analysis doesn't go far enough to determine that they also throw in all cases.

For example,

public class StaticThrow {
    static int foo = 0;
    {{ if (Math.sin(3) < 0.5) { throw new ArithmeticException("Heya"); } else { foo = 3; } }}
    public static void main(String[] args) {
        StaticThrow t = new StaticThrow();
        System.out.println(StaticThrow.foo);
    }
}

compiles, and when run throws

Exception in thread "main" java.lang.ArithmeticException: Heya
        at StaticThrow.<init>(StaticThrow.java:3)
        at StaticThrow.main(StaticThrow.java:5)
like image 33
Daniel Fischer Avatar answered Oct 11 '22 10:10

Daniel Fischer