Java-uitzonderingen op de juiste manier afhandelen

Java-uitzonderingen op de juiste manier afhandelen

Als een nieuweling in programmeren, is het concept van uitzonderingsbehandeling kan moeilijk zijn om je hoofd rond te wikkelen. Niet dat het concept op zich moeilijk is, maar de terminologie kan het geavanceerder doen lijken dan het is. En het is zo'n krachtige functie dat het vatbaar is voor misbruik en misbruik.





In dit artikel leert u wat uitzonderingen zijn, waarom ze belangrijk zijn, hoe u ze kunt gebruiken en veelvoorkomende fouten die u moet vermijden. De meeste moderne talen hebben een soort uitzonderingsbehandeling, dus als je ooit verder gaat van Java, kun je de meeste van deze tips meenemen.





Java-uitzonderingen begrijpen

Op Java is een uitzondering is een object dat aangeeft dat er iets abnormaals (of 'uitzonderlijk') is opgetreden tijdens het uitvoeren van uw toepassing. Dergelijke uitzonderingen zijn: gegooid , wat in feite betekent dat er een uitzonderingsobject wordt gemaakt (vergelijkbaar met hoe fouten worden 'opgewekt').





Het mooie is dat je het kunt vangst gegooide uitzonderingen, waarmee u de abnormale toestand kunt oplossen en uw toepassing kunt blijven uitvoeren alsof er niets mis is gegaan. Terwijl een null-pointer in C uw toepassing bijvoorbeeld kan laten crashen, kunt u met Java gooien en vangen

NullPointerException

s voordat een null-variabele een kans heeft om een ​​crash te veroorzaken.



Onthoud dat een uitzondering slechts een object is, maar met één belangrijk kenmerk: het moet worden uitgebreid vanaf de

Exception

klasse of een subklasse van





Exception

. Hoewel Java allerlei ingebouwde uitzonderingen heeft, kunt u desgewenst ook uw eigen uitzonderingen maken. Sommige van de meest voorkomende Java-uitzonderingen erbij betrekken:

  • NullPointerException
  • NumberFormatException
  • IllegalArgumentException
  • RuntimeException
  • IllegalStateException

Dus wat gebeurt er als je een uitzondering gooit?





Ten eerste kijkt Java in de directe methode om te zien of er code is die het soort exception afhandelt dat je hebt gegenereerd. Als er geen handler bestaat, wordt gekeken naar de methode die de huidige methode heeft aangeroepen om te zien of daar een handle bestaat. Zo niet, dan kijkt het naar de methode die aangeroepen heeft Dat methode, en dan de volgende methode, enz. Als de uitzondering niet wordt opgevangen, drukt de toepassing een stacktracering af en crasht vervolgens. (Eigenlijk ligt het genuanceerder dan gewoon crashen, maar dat is een geavanceerd onderwerp dat buiten het bestek van dit artikel valt.)

TOT stapel traceren is een lijst met alle methoden die Java heeft doorlopen tijdens het zoeken naar een uitzonderingshandler. Zo ziet een stacktracering eruit:

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)

Hier kunnen we veel van opsteken. Ten eerste was de gegooide uitzondering a

NullPointerException

. Het gebeurde in de

getTitle()

methode op regel 16 van Book.java. Die methode werd aangeroepen van

getBookTitles()

op regel 25 van Author.java. Dat methode werd aangeroepen van

main()

op regel 14 van Bootstrap.java. Zoals u kunt zien, maakt dit alles het debuggen gemakkelijker.

Maar nogmaals, het echte voordeel van uitzonderingen is dat je de abnormale toestand kunt 'afhandelen' door de uitzondering op te vangen, dingen recht te zetten en de toepassing te hervatten zonder te crashen.

Java-uitzonderingen gebruiken in code

Laten we zeggen dat je hebt

someMethod()

dat neemt een geheel getal en voert enige logica uit die zou kunnen breken als het geheel getal kleiner is dan 0 of groter dan 100. Dit zou een goede plek kunnen zijn om een ​​uitzondering te maken:

beste gratis ftp-client voor mac
public void someMethod(int value) {
if (value 100) {
throw new
IllegalArgumentException

Om deze uitzondering op te vangen, moet je naar waar gaan:

someMethod()

wordt genoemd en gebruik de try-catch blok :

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

Alles binnen de proberen blok wordt op volgorde uitgevoerd totdat er een uitzondering wordt gegenereerd. Zodra een uitzondering wordt gegenereerd, worden alle volgende instructies overgeslagen en springt de toepassingslogica onmiddellijk naar de vangst blok.

In ons voorbeeld voeren we het try-blok in en bellen onmiddellijk

someMethod()

. Aangezien 200 niet tussen 0 en 100 ligt, is an

IllegalArgumentException

wordt gegooid. Dit beëindigt onmiddellijk de uitvoering van

someMethod()

, slaat de rest van de logica in het try-blok over (

someOtherMethod()

wordt nooit aangeroepen), en hervat de uitvoering binnen het catch-blok.

Wat zou er gebeuren als we zouden bellen?

someMethod(50)

in plaats daarvan? De

IllegalArgumentException

nooit zou worden gegooid.

someMethod()

normaal zou uitvoeren. Het try-blok wordt normaal uitgevoerd en roept

someOtherMethod()

wanneer someMethod() is voltooid. Wanneer

someOtherMethod()

eindigt, wordt het catch-blok overgeslagen en

callingMethod()

zou doorgaan.

Merk op dat je meerdere catch-blokken per try-blok kunt hebben:

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

Houd er ook rekening mee dat een optionele Tenslotte blok bestaat ook:

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

De code binnen een definitief blok is altijd uitgevoerd, wat er ook gebeurt. Als u een return-instructie in het try-blok hebt, wordt het final-blok uitgevoerd voordat u terugkeert uit de methode. Als u nog een uitzondering in het catch-blok gooit, wordt het laatste blok uitgevoerd voordat de uitzondering wordt gegooid.

U moet het eindelijk-blok gebruiken als u objecten hebt die moeten worden opgeruimd voordat de methode eindigt. Als u bijvoorbeeld een bestand in het try-blok hebt geopend en later een uitzondering hebt gemaakt, kunt u met het laatste-blok het bestand sluiten voordat u de methode verlaat.

Merk op dat je een definitief blok kunt hebben zonder een catch-blok:

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

Hiermee kun je de nodige opschoning uitvoeren terwijl gegooide uitzonderingen de methodeaanroepstapel kunnen verspreiden (d.w.z. je wilt de uitzondering hier niet afhandelen, maar je moet nog steeds eerst opschonen).

Aangevinkte versus niet-aangevinkte uitzonderingen in Java

In tegenstelling tot de meeste talen maakt Java onderscheid tussen: gecontroleerde uitzonderingen en ongecontroleerde uitzonderingen (bijv. C# heeft alleen niet-aangevinkte uitzonderingen). Een aangevinkte uitzondering moeten worden gevangen in de methode waar de uitzondering wordt gegenereerd, anders wordt de code niet gecompileerd.

Om een ​​aangevinkte uitzondering aan te maken, breidt u uit van

Exception

. Als u een ongecontroleerde uitzondering wilt maken, breidt u uit van

RuntimeException

.

Elke methode die een gecontroleerde uitzondering genereert, moet dit aangeven in de handtekening van de methode met behulp van de worpen trefwoord. Sinds Java is ingebouwd

IOException

een gecontroleerde uitzondering is, wordt de volgende code niet gecompileerd:

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

U moet eerst verklaren dat het een gecontroleerde uitzondering genereert:

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

Merk op dat een methode kan worden gedeclareerd als het genereren van een uitzondering, maar nooit daadwerkelijk een uitzondering genereert. Toch moet de uitzondering nog steeds worden opgevangen, anders wordt de code niet gecompileerd.

Wanneer moet u aangevinkte of ongecontroleerde uitzonderingen gebruiken?

De officiële Java-documentatie heeft een pagina over deze vraag . Het vat het verschil samen met een beknopte vuistregel: 'Als redelijkerwijs kan worden verwacht dat een cliënt herstelt van een uitzondering, maak er dan een gecontroleerde uitzondering van. Als een klant niets kan doen om de uitzondering te herstellen, maak er dan een ongecontroleerde uitzondering van.'

Maar deze richtlijn kan achterhaald zijn. Aan de ene kant resulteren gecontroleerde uitzonderingen in robuustere code. Aan de andere kant heeft geen enkele andere taal uitzonderingen op dezelfde manier gecontroleerd als Java, wat twee dingen laat zien: ten eerste is de functie niet nuttig genoeg voor andere talen om het te stelen, en twee, je kunt absoluut zonder ze leven. Bovendien werken aangevinkte uitzonderingen niet goed samen met lambda-expressies die in Java 8 zijn geïntroduceerd.

Richtlijnen voor het gebruik van Java-uitzonderingen

Uitzonderingen zijn nuttig, maar gemakkelijk misbruikt en misbruikt. Hier zijn een paar tips en best practices om te voorkomen dat je er een zooitje van maakt.

  • Geef de voorkeur aan specifieke uitzonderingen boven algemene uitzonderingen. Gebruik |_+_| meer dan |_+_| indien mogelijk, gebruik anders |__+_| meer dan |_+_| wanneer mogelijk.
  • Nooit vangen |__+_| ! De |_+_| klasse breidt eigenlijk uit |__+_| , en het catch-blok werkt eigenlijk met |__+_| of een klasse die Throwable uitbreidt. Echter, de |__+_| klasse breidt ook |__+_| . uit , en je wilt nooit een |_+_| . vangen omdat |__+_| s duiden op ernstige onherstelbare problemen.
  • Nooit vangen |__+_| ! |__+_| breidt uit |_+_| , dus elk blok dat |_+_| . vangt zal ook |__+_| . vangen , en dat is een zeer belangrijke uitzondering waar je niet mee wilt rotzooien (vooral in toepassingen met meerdere threads), tenzij je weet wat je doet. Als je niet weet welke uitzondering je moet vangen, overweeg dan om niets te vangen.
  • Gebruik beschrijvende berichten om foutopsporing te vergemakkelijken. Wanneer u een uitzondering gooit, kunt u een |_+_| . opgeven bericht als argument. Dit bericht is toegankelijk in het catch-blok met de |__+_| methode, maar als de uitzondering nooit wordt opgevangen, verschijnt het bericht ook als onderdeel van de stacktracering.
  • Probeer uitzonderingen niet te vangen en te negeren. Om het ongemak van gecontroleerde uitzonderingen te omzeilen, zullen veel nieuwelingen en luie programmeurs een catch-blok opzetten, maar dit leeg laten. Slecht! Ga er altijd netjes mee om, maar als je dat niet kunt, print dan op zijn minst een stacktracering uit, zodat je weet dat de uitzondering is gegenereerd. U kunt dit doen met de |__+_| methode.
  • Pas op voor overmatig gebruik van uitzonderingen. Als je een hamer hebt, lijkt alles op een spijker. Wanneer u voor het eerst over uitzonderingen leert, voelt u zich misschien verplicht om van alles een uitzondering te maken... tot het punt waarop het grootste deel van de controlestroom van uw toepassing neerkomt op het afhandelen van uitzonderingen. Onthoud dat uitzonderingen bedoeld zijn voor 'uitzonderlijke' gebeurtenissen!

Nu moet u vertrouwd genoeg zijn met uitzonderingen om te begrijpen wat ze zijn, waarom ze worden gebruikt en hoe u ze in uw eigen code kunt opnemen. Als je het concept niet helemaal begrijpt, is dat oké! Het duurde even voordat het in mijn hoofd 'klikte', dus heb niet het gevoel dat je het moet overhaasten. Neem je tijd.

Heb je vragen? Weet u nog andere tips over uitzonderingen die ik heb gemist? Deel ze in de reacties hieronder!

Deel Deel Tweeten E-mail Een gegevensstroomdiagram maken om gegevens van elk project te visualiseren

Gegevensstroomdiagrammen (DFD) van elk proces helpen u te begrijpen hoe gegevens van de bron naar de bestemming stromen. Hier leest u hoe u het kunt maken!

Lees volgende
Gerelateerde onderwerpen
  • Programmeren
  • Java
Over de auteur Joel Lee(1524 artikelen gepubliceerd)

Joel Lee is de hoofdredacteur van MakeUseOf sinds 2018. Hij heeft een B.S. in computerwetenschappen en meer dan negen jaar professionele schrijf- en redactieervaring.

waarom laadt mijn computer niet op?
Meer van Joel Lee

Abonneer op onze nieuwsbrief

Word lid van onze nieuwsbrief voor technische tips, recensies, gratis e-boeken en exclusieve deals!

Klik hier om je te abonneren