Hur man hanterar Java -undantag på rätt sätt

Hur man hanterar Java -undantag på rätt sätt

Som programmering nybörjare, begreppet undantagshantering kan vara svårt att linda huvudet runt. Inte för att själva konceptet är svårt, men terminologin kan få det att verka mer avancerat än det är. Och det är en så kraftfull funktion att den är benägen att missbruka och missbruka.





I den här artikeln lär du dig vad undantag är, varför de är viktiga, hur du använder dem och vanliga misstag att undvika. De flesta moderna språk har någon form av undantagshantering, så om du någonsin går vidare från Java kan du ta med dig de flesta av dessa tips.





Förstå Java -undantag

I Java, en undantag är ett objekt som indikerar att något onormalt (eller 'exceptionellt') inträffade under programmets körning. Sådana undantag är kastas , vilket i grunden betyder att ett undantagsobjekt skapas (liknande hur fel 'höjs').





Skönheten är att du kan fånga kastade undantag, som låter dig hantera det onormala tillståndet och låta din applikation fortsätta att köra som om inget gick fel. Till exempel, medan en nollpekare i C kan krascha din applikation, låter Java dig kasta och fånga

NullPointerException

s innan en nullvariabel har en chans att orsaka en krasch.



Kom ihåg att ett undantag bara är ett objekt, men med en viktig egenskap: det måste förlängas från

Exception

klass eller någon underklass av





Exception

. Medan Java har alla typer av inbyggda undantag, kan du också skapa dina egna om du vill. Några av vanligaste Java -undantagen omfatta:

  • NullPointerException
  • NumberFormatException
  • IllegalArgumentException
  • RuntimeException
  • IllegalStateException

Så vad händer när du kastar ett undantag?





Först tittar Java inom den omedelbara metoden för att se om det finns kod som hanterar den typ av undantag du kastade. Om en hanterare inte existerar tittar den på metoden som kallade den aktuella metoden för att se om det finns ett handtag där. Om inte, tittar det på metoden som kallade den där metod, och sedan nästa metod, etc. Om undantaget inte upptäcks, skriver programmet ut en stapelspårning och kraschar sedan. (Egentligen är det mer nyanserat än att bara krascha, men det är ett avancerat ämne utanför denna artikels omfattning.)

TILL stack spår är en lista över alla de metoder som Java gick igenom när de letade efter en undantagshanterare. Så här ser en stackspårning ut:

Exception in thread 'main' java.lang.NullPointerException
at com.example.myproject.Book.getTitle(Book.java:16)
at com.example.myproject.Author.getBookTitles(Author.java:25)
at com.example.myproject.Bootstrap.main(Bootstrap.java:14)

Vi kan hämta mycket av detta. För det första var det kastade undantaget a

NullPointerException

. Det inträffade i

getTitle()

metod på rad 16 i Book.java. Den metoden kallades från

getBookTitles()

på rad 25 i Author.java. Den där metoden kallades från

main()

på rad 14 i Bootstrap.java. Som du kan se, gör det lättare att veta allt detta.

Men igen, den verkliga fördelen med undantag är att du kan 'hantera' det onormala tillståndet genom att fånga undantaget, ställa in saker rätt och återuppta programmet utan att krascha.

Använda Java -undantag i kod

Låt oss säga att du har

someMethod()

som tar ett heltal och kör någon logik som kan gå sönder om heltalet är mindre än 0 eller större än 100. Detta kan vara ett bra ställe att göra ett undantag:

häftiga saker att göra med en flash -enhet
public void someMethod(int value) {
if (value 100) {
throw new
IllegalArgumentException

För att fånga detta undantag måste du gå dit

someMethod()

kallas och använder try-catch block :

public void callingMethod() {
try {
someMethod(200);
someOtherMethod();
} catch (IllegalArgumentException e) {
// handle the exception in here
}
// ...
}

Allt inom Prova blocket körs i ordning tills ett undantag kastas. Så snart ett undantag kastas hoppas alla efterföljande uttalanden över och applikationslogiken hoppar direkt till fånga blockera.

I vårt exempel går vi in ​​i försöksblocket och ringer direkt

someMethod()

. Eftersom 200 inte är mellan 0 och 100, an

IllegalArgumentException

kastas. Detta avslutar omedelbart utförandet av

someMethod()

, hoppar över resten av logiken i försöksblocket (

someOtherMethod()

kallas aldrig) och återupptar körningen inom fångstblocket.

Vad skulle hända om vi ringde

someMethod(50)

istället? De

IllegalArgumentException

skulle aldrig kastas.

someMethod()

skulle köra som vanligt. Försöksblocket körs som vanligt och ringer

someOtherMethod()

när someMethod () slutförts. När

someOtherMethod()

slutar, fångstblocket skulle hoppas över och

callingMethod()

skulle fortsätta.

Observera att du kan ha flera fångstblock per provblock:

public void callingMethod() {
try {
someMethod(200);
someOtherMethod();
} catch (IllegalArgumentException e) {
// handle the exception in here
} catch (NullPointerException e) {
// handle the exception in here
}
// ...
}

Observera också att tillval till sist blocket finns också:

public void method() {
try {
// ...
} catch (Exception e) {
// ...
} finally {
// ...
}
}

Koden i ett slutligen block är alltid avrättad oavsett vad. Om du har en returseddel i försöksblocket körs det slutliga blocket innan du återgår från metoden. Om du kastar ett annat undantag i fångstblocket, utförs slutligen blocket innan undantaget kastas.

Du bör använda det slutliga blocket när du har objekt som måste rengöras innan metoden slutar. Om du till exempel öppnade en fil i försöksblocket och senare kastade ett undantag, låter du det slutliga blocket stänga filen innan du lämnar metoden.

Observera att du kan ha ett slutligen block utan ett fångstblock:

public void method() {
try {
// ...
} finally {
// ...
}
}

Detta låter dig göra alla nödvändiga städningar samtidigt som du tillåter kastade undantag att sprida upp metodinropstacken (det vill säga att du inte vill hantera undantaget här men du måste fortfarande städa först).

Kontrollerat mot okontrollerade undantag i Java

Till skillnad från de flesta språk skiljer Java mellan kontrollerade undantag och okontrollerade undantag (t.ex. C# har bara okontrollerade undantag). Ett kontrollerat undantag måste fastna i metoden där undantaget kastas annars kommer koden inte att kompilera.

För att skapa ett kontrollerat undantag, förläng från

Exception

. För att skapa ett okontrollerat undantag, förläng från

RuntimeException

.

Varje metod som kastar ett kontrollerat undantag måste markera detta i metodesignaturen med kastar nyckelord. Sedan Java är inbyggt

IOException

är ett kontrollerat undantag kommer följande kod inte att kompilera:

public void wontCompile() {
// ...
if (someCondition) {
throw new IOException();
}
// ...
}

Du måste först förklara att det kastar ett kontrollerat undantag:

public void willCompile() throws IOException {
// ...
if (someCondition) {
throw new IOException();
}
// ...
}

Observera att en metod kan förklaras som att kasta ett undantag men aldrig kasta ett undantag. Trots det måste undantaget fortfarande fångas eller annars kommer koden inte att kompileras.

När ska du använda kontrollerade eller okontrollerade undantag?

Den officiella Java -dokumentationen har en sida om denna fråga . Det sammanfattar skillnaden med en kortfattad tumregel: 'Om en klient rimligen kan förväntas återhämta sig från ett undantag, gör det till ett kontrollerat undantag. Om en klient inte kan göra något för att återhämta sig från undantaget, gör det till ett okontrollerat undantag. '

Men denna riktlinje kan vara föråldrad. Å ena sidan resulterar kontrollerade undantag i mer robust kod. Å andra sidan har inget annat språk kontrollerat undantag på samma sätt som Java, vilket visar två saker: en, funktionen är inte tillräckligt användbar för att andra språk ska stjäla den, och två, du kan absolut leva utan dem. Dessutom kontrolleras undantag inte bra med lambda -uttryck som introducerades i Java 8.

Riktlinjer för användning av Java -undantag

Undantag är användbara men missbrukas och missbrukas lätt. Här är några tips och bästa praxis som hjälper dig att undvika att röra på dem.

  • Föredrar specifika undantag framför allmänna undantag. Använd | _+_ | över | _+_ | om möjligt, använd annars | _+_ | över | _+_ | när det är möjligt.
  • Fånga aldrig | _+_ | ! Den | _+_ | klass sträcker sig faktiskt | _+_ | , och fångstblocket fungerar faktiskt med | _+_ | eller någon klass som sträcker sig Throwable. Emellertid | _+_ | klass sträcker sig också | _+_ | , och du vill aldrig fånga en | _+_ | eftersom | _+_ | s indikerar allvarliga problem som inte kan återställas.
  • Fånga aldrig | _+_ | ! | _+_ | sträcker sig | _+_ | , så alla block som fångar | _+_ | kommer också att fånga | _+_ | , och det är ett mycket viktigt undantag som du inte vill bråka med (särskilt i applikationer med flera trådar) om du inte vet vad du gör. Om du inte vet vilket undantag du ska fånga istället, överväg att inte fånga någonting.
  • Använd beskrivande meddelanden för att underlätta felsökning. När du gör ett undantag kan du ange ett | _+_ | meddelande som argument. Detta meddelande kan nås i fångstblocket med hjälp av | _+_ | metod, men om undantaget aldrig fångas kommer meddelandet också att visas som en del av stapelspåret.
  • Försök att inte fånga och ignorera undantag. För att komma runt besväret med kontrollerade undantag kommer många nybörjare och lata programmerare att skapa ett fångstblock men lämna det tomt. Dålig! Hantera alltid det graciöst, men om du inte kan, skriv ut åtminstone ett stapelspår så att du vet att undantaget kastades. Du kan göra detta med | _+_ | metod.
  • Akta dig för överanvändning av undantag. När du har en hammare ser allt ut som en spik. När du först lär dig om undantag kan du känna dig skyldig att göra allt till ett undantag ... till den punkt där det mesta av din applikations kontrollflöde handlar om undantagshantering. Kom ihåg att undantag är avsedda för 'exceptionella' händelser!

Nu borde du vara bekväm nog med undantag för att förstå vad de är, varför de används och hur du införlivar dem i din egen kod. Om du inte helt förstår konceptet är det okej! Det tog mig ett tag innan det 'klickade' i mitt huvud, så det känns inte som att du behöver skynda på det. Ta din tid.

Har du några frågor? Känner du till några andra undantagsrelaterade tips som jag missat? Dela dem i kommentarerna nedan!

Dela med sig Dela med sig Tweet E-post Hur man skapar ett dataflödesdiagram för att visualisera data från alla projekt

Dataflödesdiagram (DFD) för alla processer hjälper dig att förstå hur data flödar från källan till destinationen. Så här skapar du det!

Läs Nästa
Relaterade ämnen
  • Programmering
  • Java
Om författaren Joel Lee(1524 artiklar publicerade)

Joel Lee är chefredaktör för MakeUseOf sedan 2018. Han har en B.S. i datavetenskap och över nio års professionell skriv- och redigeringserfarenhet.

spela Windows XP -spel på Windows 10
Mer från Joel Lee

Prenumerera på vårt nyhetsbrev

Gå med i vårt nyhetsbrev för tekniska tips, recensioner, gratis e -böcker och exklusiva erbjudanden!

Klicka här för att prenumerera