Hvorfor tillader compileren kast, når metoden aldrig vil kaste undtagelsen
throws
klausul er en del af metodens kontrakt. Det kræver, at den, der kalder metoden, opfører sig, som om den angivne undtagelse kan blive kastet af metoden (dvs. enten fange undtagelsen eller erklære deres egen throws
klausul).
Det er muligt, at den oprindelige version af en metode ikke kaster undtagelsen angivet i throws
klausul, men en fremtidig version kan kaste den uden at bryde API'en (dvs. enhver eksisterende kode, der kalder metoden, vil stadig bestå kompilering).
Det modsatte er også muligt. Hvis metoden brugt til at kaste undtagelsen angivet i throws
klausul, men en fremtidig version af den kaster den ikke længere, du bør beholde throws
klausul for ikke at bryde eksisterende kode, der bruger din metode.
Første eksempel:
Antag, at du har denne kode, som bruger methodB
:
private static void methodA() {
methodB(); // doesn't have throws IOException clause yet
}
Hvis du senere vil ændre methodB
at kaste IOException
, methodA
vil stoppe med at bestå kompilering.
Andet eksempel:
Antag, at du har denne kode, som bruger methodB
:
private static void methodA() {
try {
methodB(); // throws IOException
}
catch (IOException ex) {
}
}
Hvis du fjerner throws
klausul fra en fremtidig version af methodB
, methodA
vil ikke bestå kompileringen længere.
Dette eksempel er ikke særlig interessant, når methodA
er private
, fordi det kun kan bruges lokalt (inden for samme klasse, hvor det er nemt at ændre alle de metoder, der kalder det).
Men hvis det bliver public
, du ved ikke, hvem der bruger (eller vil bruge) din metode, så du har ingen kontrol over al den kode, der kan gå i stykker som følge af tilføjelse eller fjernelse af throws
klausul.
Og hvis det er en instansmetode, er der en anden grund til at tillade throws
klausul, selvom du ikke kaster undtagelsen - metoden kan tilsidesættes, og den tilsidesættende metode kan kaste undtagelsen, selvom basisklasseimplementeringen ikke gør det.
Fordi signaturen definerer kontrakten for metoden. Selvom metoden ikke kaster en IOException nu, vil den måske gøre det i fremtiden, og du vil forberede dig på den mulighed.
Antag, at du bare leverer en dummy-implementering til metoden indtil videre, men du ved, at senere vil den faktiske implementering potentielt kaste en IOException. Hvis compileren forhindrede dig i at tilføje denne throws-klausul, ville du være tvunget til at omarbejde alle kald ( rekursivt) til denne metode, når du har angivet den faktiske implementering af metoden.