Какъв е смисълът от catching
и след това също throwing
и Exception
като по-долу? Лоша практика ли е да се правят и двете?
try{
//something
} catch (Exception e){
throw new RuntimeException("reason for exception");
}
Какъв е смисълът от catching
и след това също throwing
и Exception
като по-долу? Лоша практика ли е да се правят и двете?
try{
//something
} catch (Exception e){
throw new RuntimeException("reason for exception");
}
Обикновено такъв код се използва за повторно обвиване на изключенията, което означава трансформиране на типа на изключението. Обикновено правите това, когато сте ограничени в това какви изключения са разрешени извън вашия метод, но вътрешно могат да се случат други видове изключения. Например:
class MyServiceImplementaiton implements MyService {
void myService() throws MyServiceException { // cannot change the throws clause here
try {
.... // Do something
} catch(IOException e) {
// re-wrap the received IOException as MyServiceException
throw new MyServiceException(e);
}
}
}
Този идиом позволява да продължите да разпространявате изключения към повикващия, като същевременно се съобразявате с клаузата за хвърляния в интерфейса и скривате подробностите за вътрешните елементи (фактът, че могат да се случат IOExceptions).
На практика това винаги е по-добре от просто извикване на e.printStackTrace()
, което всъщност ще "погълне" условието за грешка и ще остави останалата част от програмата да работи, сякаш нищо не се е случило. В това отношение поведението на Eclipse е доста лошо, тъй като има тенденция да пише автоматично такива конструкции с лоша практика, ако разработчикът не е внимателен.
Това се нарича повторно хвърляне на изключение и е често срещан модел.
Позволява ви да промените класа на изключението (както в този случай) или да добавите повече информация (тук също така, стига този низ за грешка да има смисъл).
Често е добра идея да прикачите оригиналното изключение:
throw new RuntimeException("cause of the problem", e);
Повторното хвърляне като непроверено изключение (RuntimeException) понякога е необходимо, когато все още искате да хвърлите изключение, но API на вашия метод не позволява проверено изключение.
throw e;
... OP просто създава ново изключение (от catch блок)...
- person Codebender; 26.10.2015
Във вашия пример Exception
е уловен и RuntimeException
е хвърлен, което ефективно замества (потенциално) проверено изключение с непроверено изключение, което не трябва да се обработва от повикващия, нито да се декларира от хвърлящия метод в клауза throws
.
Няколко примера :
Този код преминава компилация:
public void SomeMethod ()
{
try {
//something
} catch (Exception e){
throw new RuntimeException("reason for exception");
}
}
Този код не преминава компилация (ако приемем, че "нещо" може да хвърли проверено изключение):
public void SomeMethod ()
{
//something
}
Алтернатива на улавянето на Exception
и хвърлянето на непроверено изключение (т.е. RuntimeException
) е да добавите throws
клауза:
public void SomeMethod () throws Exception
{
//something
}
Това е един случай на използване на улавяне на един тип изключение и хвърляне на друго. Друг случай на използване е да хванете един тип изключение и да хвърлите друг тип проверено изключение (което вашият метод декларира в своята клауза throws
). Понякога се прави, за да се групират множество изключения, които могат да бъдат хвърлени вътре в метод, и да се хвърли само един тип изключение към извикващия метода (което ги улеснява да напишат кода за обработка на изключения и има смисъл, ако всички тези изключения трябва да се третират по същия начин).
e.printStackTrace()
в своите catch блокове. Откъде взехте това/защо хвърляте ново изключение? Смисълът на прихващането е да се предотврати срив, а не да се срине програмата с напълно ново изключение, което не съдържа нищо от оригиналната информация. - person Arc676   schedule 26.10.2015e.printStackTrace()
. Всъщност никога не съм писал това и никога не бих го препоръчал: трябва или да влезете правилно, или да хвърлите отново. - person Tunaki   schedule 26.10.2015