2017-01-24 33 views
14

Po przeczytaniu Why can't overriding methods throw exceptions, to rozumieć, że w przypadku metody zadeklarowane jako generuje sprawdzone wyjątek nadrzędnym Sposób podklasy tylko może zadeklarować wyrzucić ten wyjątek lub podklasy:Wywoływanie nadrzędne sposób, że rzuty sprawdzone wyjątek

class A { 
    public void foo() throws IOException {..} 
} 

class B extends A { 
    @Override 
    public void foo() throws SocketException {..} // allowed 

    @Override 
    public void foo() throws SQLException {..} // NOT allowed 
} 

Tak więc, ponieważ mogę zadeklarować metodę nadpisującą jako rzutuje dowolną podklasę z , mogę zadeklarować metodę przesłaniania.

W moim programie chcę wywołać metodę przesłaniania zadeklarowaną jako rzutnie FileNotFoundException IS-A IOException. również obsługiwane z bloku try-catch

import java.io.*; 
class Sub extends Super{ 
    public static void main (String [] args){ 
     Super p = new Sub(); 
     try { 
      p.doStuff(); 
     }catch(FileNotFoundException e){ 

     } 
    } 
    public void doStuff() throws FileNotFoundException{} 
} 

class Super{ 
    public void doStuff() throws IOException{} 
} 

Ale ja dostaję ten błąd kompilacji: Screenshot

Sub.java:6: error: unreported exception IOException; must be caught or declared to be thrown 
        p.doStuff(); 
          ^

Jaki jest powód? Jestem nieco zdezorientowany, ponieważ wszystko, co klasa Base ma również dostępne dla podklas.

Również znacznie bardziej myląca jest możliwość złapania Exception i Throwable Oprócz IOException (Przeciwieństwo nadrzędnego pojęcia).

+3

Niektóre osoby mogą mieć zablokowane obrazy. Czy możesz również skopiować wkleić błąd kompilacji w swoim pytaniu. – CKing

+2

@CKing dodane teraz – Pauwelyn

Odpowiedz

10

What is the reason for that? I'm a little confused because everything that the Base class has also available to the subclasses.

Trzeba złapać IOException a nie FilenotFoundException. Wynika to z faktu, że podczas gdy metoda doStuff z podklasy zostanie wywołana w czasie wykonywania, kompilator jeszcze o tym nie wie. Wie tylko o metodzie doStuff w super klasie, która deklaruje, że jest to throws i IOException.

Aby zaadresować edycję: blok catch może wybrać wychwycenie dokładnego wyjątku oczekiwanego w bloku try lub może wybrać przechwycenie nadklasy wyjątku. Rozumowanie tego nie ma nic wspólnego z nadpisaniem metody.

2

Dzieje się tak, ponieważ używasz obiektu typu statycznego Super. Kompilator nie może wiedzieć, że w czasie wykonywania p wskazuje obiekt Sub, więc chce przechwycić wyjątki wygenerowane przez metodę zadeklarowaną w klasie Super

14

Odsyłacz do obiektu jest typu Super, nawet jeśli wiadomo, że jest obiekt w czasie wykonywania. Dlatego kompilator sprawdza definicję metody Super i podaje ten błąd kompilacji.

Byłoby nie różni się od otrzymuję następujący błąd kompilatora:

Object o = new String("Hello World"); 
o.charAt(2); //Obviously not allowed 

Ważne jest, aby pamiętać, że klauzula throws jest częścią definicji metody.

+1

Ale java.lang.Object nie ma metody "charAt", podczas gdy zarówno 'Super' jak i' Sub' mają – Pauwelyn

+2

uzgodnione. Jednak główny jest dokładnie taki sam, kompilator sprawdza tylko, czy wywoływane metody znajdują się w typie odniesienia ('Object' w moim przykładzie,' Super' w twoim przypadku). – StuPointerException

2

Ponieważ wykonuje kontrole według zadeklarowanego typu, w tym przypadku Super.

Nie jest znane (lub zaznaczone), że Twój p będzie zawierał tylko instancje Sub. Nie byłoby też sensu definiować zmiennej nadklasy i używać jej tylko i tylko dla jednej konkretnej podklasy.

Twój Super p zawiera instancję Super.class. Jego metoda: doStuff() może rzucić wszystko, co rozszerza się o IOException, powiedzmy, UnsupportedEncodingException, ale próbujesz złapać tylko dla FileNotFoundException, więc Unsupported... może zostać wyrzucony i musi zostać obsłużony.

5

Kompilator nie bierze pod uwagę typu obiektu, ale typu odniesienia, którego używasz, czyli Super.

Jako Super.doStuff() throws IOException, to jest to, co musisz złapać.

BTW Gorąco polecam używanie IDE, okaże się bardziej produktywne.

+0

W jaki sposób mogę użyć również 'Exception' i' Throwable' Oprócz 'IOException'? Jest to przeciwieństwo Overriding, które może zadeklarować tylko wyrzucenie tego wyjątku lub jego podklasy. – Pauwelyn

+0

@Pau metoda przesłonięta nie może ich wyrzucić, ale można je przechwycić –

3

Deklarując p jako Super

Super p = ... 

kompilator wie p jest jakiś Super. Super 's doStuff() wyrzuca IOException, ale twój kod przechwytuje tylko specjalny przypadek IOException, FileNotFoundException. Jeśli chcesz powiedzieć kompilatorowi, to z pewnością jest to Sub, a nie Super tylko zadeklaruj p jako .

W tym przypadku jest to wyraźny nie zostały zadeklarowane jako Sub ale jak Super więc każdy Super lub jego Childs może wystąpić i rzucać żadnych IOException który może nie być FileNotFoundException lub którykolwiek z nim to Childs.

Powiązane problemy