2013-02-23 15 views
7

Według JLS: jest to błąd podczas kompilacji, jeśli inicjator zmiennej instancji lub inicjalizator instancji klasy o podanej nazwie może rzucić zaznaczoną klasę wyjątków, chyba że ta klasa wyjątków lub jedna z jej nadklas jest jawnie zadeklarowana w klauzuli throws każdego konstruktora swojej klasy i klasa ma co najmniej jeden jawnie zadeklarowany konstruktor.Sprawdzany blok wyjątku i inicjalizatora

Więc jeśli mogę to zrobić -

class A{ 
{ 
    throw new FileNotFoundException(); 
} 
public A() throws IOException{ 
    // TODO Auto-generated constructor stub 
} 
} 

Daje to błąd czasu kompilacji „inicjator musi wypełnić normalnie”

podczas

class A{ 
{ 
    File f=new File("a"); 
    FileOutputStream fo=new FileOutputStream(f); 
    fo.write(3); 
} 
public A() throws IOException{ 
    // TODO Auto-generated constructor stub 
} 
} 

Kod ten nie wykazuje żadnego czasu kompilacji błąd. Dlaczego poprzedni kod nie kompiluje się, nawet jeśli zadeklarowałem klauzulę throws w konstruktorze?

+0

Powiedzieliście blokowi inicjalizatora, aby rzucił nieuwarunkowany wyjątek, czego jeszcze można się spodziewać? – skuntsel

Odpowiedz

4

Powinny istnieć pewne warunki, gdy inicjator może faktycznie ukończyć bez żadnego wyjątku.

W twoim przypadku nie ma mowy, aby tak się stało.

Spróbuj:

if(/*condition-to-fail*/) { 
    /*Not always, only when something is wrong. Compiler knows that.*/ 
    throw new FileNotFoundException(); 
} 

Aktualizacja:

Poniższe oświadczenie jest rzeczywiście rzuca wyjątek.

throw new FileNotFoundException(); 

Bez żadnego warunku wykonanie programu zawsze tam się kończy.

podczas gdy w następstwie -

FileOutputStream fo = new FileOutputStream(f); 

konstruktor FileOutputStream(File) nie zawsze rzucać ten wyjątek.

Klauzula throws w public FileOutputStream(File file) throws FileNotFoundException mówi tylko, że może rzucić ten wyjątek, i zrobi to tylko wtedy, gdy w czasie wykonywania plik nie zostanie znaleziony, inaczej nie.

+0

+1, który działa. ale dlaczego potrzebujemy warunkowego oświadczenia? nie możemy po prostu rzucić pracy wyjątku? – PermGenError

+2

@PremGenError: To tak jak pisanie kodu po instrukcji return bez sprawdzania stanu. Kompilator może to również wykryć, w tym przypadku. –

+0

ładne ... dzięki :) – PermGenError

2

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.

...

+0

+1 odpowiedź, która podaje rzeczywisty powód. – assylias

1

W pierwszym przypadku kompilator już wiedząc, że instancja initializer nie zamierza zakończyć zwykle dlatego, że wyraźnie rzucony FileNotFoundException tam. Możesz powiedzieć, że jest to ocena inteligentnego kodu kompilatora. Ale jeśli sprawisz, że kompilator uwierzy, że inicjator instancji ma choćby najmniejszą szansę na pomyślne ukończenie, kompilator nie będzie narzekał podczas kompilacji. Na przykład w kodzie podanym poniżej, chociaż plik IDonotexist.txt nie istnieje w moim katalogu i jestem pewien, że rzuciłby on FileNotFoundException, ale nadal kompilator pozwoliłby mu się pomyślnie skompilować. Dlaczego? Ponieważ istnienie pliku jest sprawdzane podczas wykonywania kodu, a nie podczas kompilacji.

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(); 
    } 
} 

Jest to podobne do przypadku ostatniej inicjalizacji zmiennej. Na przykład w poniższym kodzie, kompilator pokaże błąd czasu kompilacji

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 
    } 

Ale jeśli mogę zastąpić warunek if (k == 90) z if(true) następnie kompilator nie pokaże błędu. Ponieważ kompilator wiedząc, że i z pewnością zostanie przypisany pewną wartość.

Powiązane problemy