Reputation: 86
According to JLS: it is a compile-time error if an instance variable initializer or instance initializer of a named class can throw a checked exception class, unless that exception class or one of its superclasses is explicitly declared in the throws clause of each constructor of its class and the class has at least one explicitly declared constructor.
So if I do this -
class A{
{
throw new FileNotFoundException();
}
public A() throws IOException{
// TODO Auto-generated constructor stub
}
}
This gives a compile time error "initializer must complete normally"
while
class A{
{
File f=new File("a");
FileOutputStream fo=new FileOutputStream(f);
fo.write(3);
}
public A() throws IOException{
// TODO Auto-generated constructor stub
}
}
This code doesn't show any compile time error. Why doesn't the previous code compile even if I have declared a throws clause in the constructor?
Upvotes: 7
Views: 596
Reputation: 51030
There should be some condition when the initializer can actually complete without any exception.
In your case there is no way that it can happen.
Try:
if(/*condition-to-fail*/) {
/*Not always, only when something is wrong. Compiler knows that.*/
throw new FileNotFoundException();
}
Update:
The following statement is actually throwing the exception.
throw new FileNotFoundException();
So with no condition your program execution always ends there.
While in the following -
FileOutputStream fo = new FileOutputStream(f);
the constructor FileOutputStream(File)
doesn't always throw that exception.
The throws clause in public FileOutputStream(File file) throws FileNotFoundException
is only saying that it might throw that exception, and it will do it only if at runtime the file is not found otherwise not.
Upvotes: 4
Reputation: 13066
In first Case compiler is already knowing that the instance initializer is never going to complete normally because you have explicitly thrown FileNotFoundException
over there. You can say it the smart code assessment of the compiler. But if you make the compiler to believe that the instance initializer has even a slightest chance of completing successfully then compiler won't complain while compilation. For example in the code given below although file IDonotexist.txt
does not exist on my directory and I am sure that it would throw FileNotFoundException
but still compiler would let it compile successfully . Why? Because the existence of file is checked during Execution of code , not while compilation.
class A
{
{
FileReader fr = new FileReader(new File("IDonotexist.txt"));
}
public A() throws IOException
{
// TODO Auto-generated constructor stub
}
public static void main(String st[])throws Exception
{
A a = new A();
}
}
This is similar to the case of final variable initialization. For Example in following code, the compiler will show compile time error
public void calling()
{
final int i;
int k = 90;
if ( k == 90)
{
i = 56;
}
System.out.println(i);//Compiler will show error here as: variable i might not have been initialized
}
But if i replace the condition if ( k == 90)
with if(true)
then compiler won't show error. Because compiler now knowing that i
is definitely going to be assigned some value.
Upvotes: 1
Reputation: 45443
http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.6
It is a compile-time error if an instance initializer cannot complete normally
http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.21
A non-empty block that is not a switch block can complete normally iff the last statement in it can complete normally.
...
The if statement, whether or not it has an else part, is handled in an unusual manner. For this reason, it is discussed separately at the end of this section.
...
in order to allow the if statement to be used conveniently for "conditional compilation" purposes, the actual rules differ.
...
Upvotes: 2