Hoe bepaal je in Java (of een andere taal met aangevinkte uitzonderingen) bij het maken van je eigen uitzonderingsklasse of deze moet worden aangevinkt of niet?
Mijn instinct zegt dat een gecontroleerde uitzondering nodig zou zijn in gevallen waarin de beller op een productieve manier zou kunnen herstellen, terwijl een ongecontroleerde uitzondering meer zou zijn voor onherstelbare gevallen, maar ik zou geïnteresseerd zijn in andermans gedachten.
Antwoord 1, autoriteit 100%
Aangevinkte uitzonderingen zijn geweldig, zolang je maar begrijpt wanneer ze moeten worden gebruikt. De Java-kern-API volgt deze regels voor SQLException (en soms voor IOException) niet en daarom zijn ze zo verschrikkelijk.
Aangevinkte uitzonderingenmoeten worden gebruikt voor voorspelbare, maar onvermijdbarefouten die redelijkerwijs kunnen worden hersteld.
Niet-aangevinkte uitzonderingenmoeten voor al het andere worden gebruikt.
Ik zal dit voor je uitleggen, omdat de meeste mensen niet begrijpen wat dit betekent.
- Voorspelbaar maar niet te voorkomen: de beller heeft er alles aan gedaan om de invoerparameters te valideren, maar een omstandigheid buiten zijn controle heeft ertoe geleid dat de bewerking is mislukt. U probeert bijvoorbeeld een bestand te lezen, maar iemand verwijdert het tussen het moment dat u controleert of het bestaat en het moment waarop de leesbewerking begint. Door een gecontroleerde uitzondering te declareren, vertelt u de beller om te anticiperen op deze fout.
- Redelijk om van te herstellen: het heeft geen zin om bellers te vertellen dat ze moeten anticiperen op uitzonderingen waarvan ze niet kunnen herstellen. Als een gebruiker probeert te lezen uit een niet-bestaand bestand, kan de beller hem om een nieuwe bestandsnaam vragen. Aan de andere kant, als de methode faalt vanwege een programmeerfout (ongeldige methode-argumenten of implementatie van een foutieve methode), kan de toepassing niets doen om het probleem halverwege de uitvoering op te lossen. Het beste wat het kan doen is het probleem registreren en wachten tot de ontwikkelaar het op een later tijdstip oplost.
Tenzij de uitzondering die u maakt voldoet aan allevan de bovenstaande voorwaarden, moet deze een niet-aangevinkte uitzondering gebruiken.
Evalueer opnieuw op elk niveau: soms is de methode die de aangevinkte uitzondering opvangt niet de juiste plaats om de fout af te handelen. Bedenk in dat geval wat redelijk is voor uw eigen bellers. Als de uitzondering voorspelbaar, onvermijdbaar en redelijk is om van te herstellen, moet u zelf een aangevinkte uitzondering maken. Als dat niet het geval is, moet u de uitzondering in een niet-aangevinkte uitzondering plaatsen. Als u deze regel volgt, zult u merken dat u aangevinkte uitzonderingen omzet in niet-aangevinkte uitzonderingen en vice versa, afhankelijk van de laag waarin u zich bevindt.
Voor zowel aangevinkte als niet-gecontroleerde uitzonderingen, gebruik het juiste abstractieniveau. Een coderepository met twee verschillende implementaties (database en bestandssysteem) moet bijvoorbeeld voorkomen dat implementatiespecifieke details worden onthuld door SQLException
of IOException
te gebruiken. In plaats daarvan zou het de uitzondering moeten inpakken in een abstractie die alle implementaties omvat (bijv. RepositoryException
).
Antwoord 2, autoriteit 22%
Van Een Java-leerling:
Als zich een uitzondering voordoet, moet u:
ofwel de uitzondering opvangen en afhandelen,
of vertel de compiler dat je het niet aankan
het door te verklaren dat uw methode
gooit die uitzondering, dan de code
die jouw methode gebruikt zal moeten
omgaan met die uitzondering (zelfs het ook)
kan ervoor kiezen om te verklaren dat het gooit
de uitzondering als het het niet aankan).Compiler controleert of we dat hebben gedaan
een van de twee dingen (vangen, of
verklaren). Dus deze heten Gecontroleerd
uitzonderingen. Maar fouten en runtime
Uitzonderingen worden niet gecontroleerd door
compiler (ook al kun je kiezen)
te vangen, of te verklaren, het is niet
vereist). Deze twee heten dus
Niet-aangevinkte uitzonderingen.Fouten worden gebruikt om die weer te geven
omstandigheden die zich voordoen buiten de
toepassing, zoals crash van de
systeem. Runtime-uitzonderingen zijn:
gebeurt meestal door een fout in de
applicatie logica. Je kunt het niet doen
alles in deze situaties. Wanneer
runtime-uitzondering optreedt, moet u:
herschrijf uw programmacode. Dus deze
worden niet gecontroleerd door de compiler. Deze
runtime-uitzonderingen zullen worden ontdekt in
ontwikkel- en testperiode. Dan
we moeten onze code refactoren om te verwijderen
deze fouten.
Antwoord 3, autoriteit 19%
De regel die ik gebruik is: gebruik nooit ongecontroleerde uitzonderingen! (of wanneer je er geen weg omheen ziet)
Er is een sterk argument voor het tegenovergestelde: gebruik nooit gecontroleerde uitzonderingen. Ik ben terughoudend om partij te kiezen in het debat, maar er lijkt een brede consensus te zijn dat het invoeren van gecontroleerde uitzonderingen achteraf een verkeerde beslissing was. Schiet alsjeblieft niet op de boodschapper en verwijs naar dieargumenten.
Antwoord 4, autoriteit 18%
Op elk systeem dat groot genoeg is, met veel lagen, zijn gecontroleerde uitzonderingen nutteloos, omdat je hoe dan ook een strategie op architecturaal niveau nodig hebt om te bepalen hoe de uitzondering wordt afgehandeld (gebruik een foutbarrière)
Met aangevinkte uitzonderingen wordt uw foutafhandelingsstrategie microbeheerd en ondraaglijk op elk groot systeem.
Meestal weet u niet of een fout “herstelbaar” is, omdat u niet weet in welke laag de aanroeper van uw API zich bevindt.
Stel dat ik een StringToInt-API maak die de tekenreeksrepresentatie van een geheel getal omzet in een Int. Moet ik een gecontroleerde uitzondering gooien als de API wordt aangeroepen met de “foo” -reeks? Is het herstelbaar? Ik weet het niet, want in zijn laag heeft de aanroeper van mijn StringToInt API de invoer mogelijk al gevalideerd, en als deze uitzondering wordt gegenereerd, is dit een bug of een gegevensbeschadiging en kan deze laag niet worden hersteld.
In dit geval wil de aanroeper van de API de uitzondering niet opvangen. Hij wil alleen de uitzondering “opborrelen”. Als ik een aangevinkte uitzondering heb gekozen, heeft deze beller genoeg nutteloze catch-blokkering om de uitzondering kunstmatig terug te draaien.
Wat herstelbaar is, hangt meestal af van de aanroeper van de API, niet van de schrijver van de API. Een API mag geen aangevinkte uitzonderingen gebruiken, omdat alleen niet-aangevinkte uitzonderingen het mogelijk maken om een uitzondering te vangen of te negeren.
Antwoord 5, autoriteit 11%
Je hebt gelijk.
Niet-aangevinkte uitzonderingenworden gebruikt om het systeem snel te laten falenwat een goede zaak is. U moet duidelijk aangeven wat uw methode verwacht om goed te werken. Op deze manier kunt u de invoer slechts één keer valideren.
Bijvoorbeeld:
/**
* @params operation - The operation to execute.
* @throws IllegalArgumentException if the operation is "exit"
*/
public final void execute( String operation ) {
if( "exit".equals(operation)){
throw new IllegalArgumentException("I told you not to...");
}
this.operation = operation;
.....
}
private void secretCode(){
// we perform the operation.
// at this point the opreation was validated already.
// so we don't worry that operation is "exit"
.....
}
Om een voorbeeld te geven. Het punt is dat als het systeem snel faalt, je weet waar en waarom het faalde. Je krijgt een stacktrace zoals:
IllegalArgumentException: I told you not to use "exit"
at some.package.AClass.execute(Aclass.java:5)
at otherPackage.Otherlass.delegateTheWork(OtherClass.java:4569)
ar ......
En je weet wat er is gebeurd. De OtherClass in de “delegateTheWork”-methode ( op regel 4569 ) riep je klasse aan met de “exit” -waarde, zelfs als dat niet zou moeten, enz.
Anders zou je validaties over je hele code moeten sprenkelen en dat is foutgevoelig. Bovendien is het soms moeilijk om bij te houden wat er fout is gegaan en kunt u urenlang frustrerend debuggen verwachten
Hetzelfde gebeurt met NullPointerExceptions. Als je een klasse van 700 regels hebt met zo’n 15 methoden, die 30 attributen gebruikt en geen van hen kan null zijn, in plaats van in elk van die methoden te valideren voor nullabiliteit, zou je al die attributen alleen-lezen kunnen maken en ze valideren in de constructor of fabrieksmethode.
public static MyClass createInstane( Object data1, Object data2 /* etc */ ){
if( data1 == null ){ throw NullPointerException( "data1 cannot be null"); }
}
// the rest of the methods don't validate data1 anymore.
public void method1(){ // don't worry, nothing is null
....
}
public void method2(){ // don't worry, nothing is null
....
}
public void method3(){ // don't worry, nothing is null
....
}
Aangevinkte uitzonderingenZijn handig wanneer de programmeur (u of uw collega’s) alles goed heeft gedaan, de invoer heeft gevalideerd, tests heeft uitgevoerd en alle code perfect is, maar de code verbinding maakt met een derde party-webservice die mogelijk niet beschikbaar is (of een bestand dat u gebruikte, is verwijderd door een ander extern proces, enz.). De webservice kan zelfs worden gevalideerd voordat de verbinding wordt geprobeerd, maar tijdens de gegevensoverdracht is er iets misgegaan.
In dat scenario kunnen jij of je collega’s er niets aan doen. Maar toch moet je iets doen en de applicatie niet gewoon laten sterven en verdwijnen in de ogen van de gebruiker. U gebruikt daarvoor een aangevinkte uitzondering en handelt de uitzondering af, wat kunt u doen als dat gebeurt? meestal, gewoon om te proberen de fout te loggen, waarschijnlijk uw werk op te slaan (het app-werk) en een bericht aan de gebruiker te presenteren . ( De site blabla is uit de lucht, probeer het later opnieuw enz. )
Als de aangevinkte uitzondering te veel wordt gebruikt ( door de “throw Exception” toe te voegen aan de handtekeningen van alle methoden ), dan wordt uw code erg kwetsbaar, omdat iedereen die uitzondering (omdat deze te algemeen is) en de kwaliteit van de code zal negeren zal ernstig worden aangetast.
Als u ongecontroleerde uitzonderingen te veel gebruikt, zal er iets soortgelijks gebeuren. De gebruikers van die code weten niet of er iets mis kan gaan en veel proberen{…}catch( Throwable t ) zal verschijnen.
6, Autoriteit 7%
Het is niet alleen een kwestie van het vermogen om te herstellen van de uitzondering. Wat er ook belangrijkst is, is naar mijn mening of de beller geïnteresseerd is in het vangen van de uitzondering of niet.
Als u een bibliotheek schrijft die elders wordt gebruikt, of een lagere laag in uw toepassing, vraag u zich dan of de beller geïnteresseerd is in het vangen (weten van) uw uitzondering. Als hij dat niet is, gebruik dan een ongecontroleerde uitzondering, zodat u hem niet onnodig instelt.
Dit is de filosofie die door veel kaders wordt gebruikt. Spring and Hibernate, in het bijzonder, komen in de zin – ze converteren bekende gecontroleerde uitzondering op ongecontroleerde uitzondering precies omdat gecontroleerde uitzonderingen overbodig zijn in Java. Een voorbeeld waar ik aan kan bedenken is de JsonException van JSON.org, die een gecontroleerde uitzondering is en meestal irritant is – het moet niet aangevinkt zijn, maar de ontwikkelaar heeft het gewoon niet door gedacht.
Trouwens, meestal wordt het belang van de beller in de uitzondering rechtstreeks gecorreleerd aan het vermogen om te herstellen van de uitzondering, maar dat is niet altijd het geval.
Antwoord 7, autoriteit 3%
Je kunt het een aangevinkte of niet-gecontroleerde uitzondering noemen; echter, beidesoorten uitzonderingen kunnen worden opgevangen door de programmeur, dus het beste antwoord is: schrijf alvan uw uitzonderingen als niet aangevinkten documenteer ze . Op die manier kan de ontwikkelaar die uw API gebruikt, kiezen of hij of zij die uitzondering wil opvangen en iets wil doen. Gecontroleerde uitzonderingen zijn een complete verspilling van ieders tijd en het maakt je code tot een schokkende nachtmerrie om naar te kijken. Een goede unit-test zal dan eventuele uitzonderingen aan het licht brengen die u mogelijk moet opvangen en waarmee u iets moet doen.
Antwoord 8, autoriteit 3%
Aangevinkte uitzondering:
Als de klant kan herstellen van een uitzondering en wil doorgaan, gebruik dan de aangevinkte uitzondering.
Niet-aangevinkte uitzondering:
Als een klant niets kan doen na de uitzondering, maak dan een niet-aangevinkte uitzondering aan.
Voorbeeld: als van u wordt verwacht dat u een rekenkundige bewerking uitvoert in een methode A() en op basis van de uitvoer van A(), moet u een andere bewerking uitvoeren. Als de uitvoer null is van methode A() die u niet verwacht tijdens de runtime, wordt van u verwacht dat u Null-pointeruitzondering genereert, wat Runtime-uitzondering is.
Raadpleeg hier
Antwoord 9
Hier wil ik mijn mening delen die ik heb na vele jaren ontwikkelingservaring:
-
Uitzondering aangevinkt. Dit is een onderdeel van de zakelijke use-case of gespreksstroom, dit is een onderdeel van de applicatielogica die we wel of niet verwachten. Bijvoorbeeld verbinding geweigerd, voorwaarde is niet voldaan enz. We moeten het afhandelen en het overeenkomstige bericht aan de gebruiker tonen met instructies wat er is gebeurd en wat vervolgens te doen (probeer het later opnieuw, enz.).
Ik noem het meestal een uitzondering voor nabewerking of een uitzondering voor “gebruikers”. -
Uitzondering uitgevinkt. Dit is een onderdeel van de programmeeruitzondering, een fout in het programmeren van softwarecode (bug, defect) en weerspiegelt een manier waarop programmeurs API moeten gebruiken volgens de documentatie. Als een extern lib/framework-document zegt dat het gegevens in een bepaald bereik en niet-null verwacht, omdat NPE of IllegalArgumentException wordt gegenereerd, moet de programmeur dit verwachten en de API correct gebruiken volgens de documentatie. Anders wordt de uitzondering gegooid.
Ik noem het meestal pre-processing-uitzondering of “validatie”-uitzondering.
Op doelgroep. Laten we het nu hebben over de doelgroep of groep mensen waarvoor de uitzonderingen zijn ontworpen (volgens mijn mening):
- Uitzondering aangevinkt. Doelgroep zijn gebruikers/klanten.
- Niet-aangevinkte uitzondering. Doelgroep zijn ontwikkelaars. Met andere woorden: niet-aangevinkte uitzonderingen zijn alleen bedoeld voor ontwikkelaars.
Per levenscyclusfase van applicatieontwikkeling.
- Gecontroleerde uitzondering is ontworpen om gedurende de hele productielevenscyclus te bestaan als normaal en verwacht mechanisme dat een toepassing uitzonderlijke gevallen afhandelt.
- Niet-aangevinkte uitzondering is ontworpen om alleen te bestaan tijdens de levenscyclus van applicatieontwikkeling/testen, ze moeten allemaal in die tijd worden opgelost en mogen niet worden gegenereerd wanneer een applicatie al in productie is.
De reden waarom frameworks meestal ongecontroleerde uitzonderingen gebruiken (Spring bijvoorbeeld) is dat het framework de bedrijfslogica van je applicatie niet kan bepalen, dit is aan de ontwikkelaars om vervolgens te achterhalen en hun eigen logica te ontwerpen.
Antwoord 10
Ik ben het eens met de voorkeur voor ongecontroleerde uitzonderingen als regel, vooral bij het ontwerpen van een API. De beller kan er altijd voor kiezen om een gedocumenteerde, ongecontroleerde uitzondering op te vangen. Je dwingt de beller gewoon niet onnodig.
Ik vind gecontroleerde uitzonderingen nuttig op een lager niveau, als implementatiedetails. Het lijkt vaak een beter controlemechanisme dan het moeten beheren van een gespecificeerde fout “retourcode”. Het kan soms ook helpen om de impact te zien van een idee voor een codewijziging op een laag niveau… declareer een gecontroleerde uitzondering stroomafwaarts en kijk wie dat zou moeten aanpassen. Dit laatste punt is niet van toepassing als er veel generieke: catch(Exception e)of gooit Exceptionzijn, wat meestal toch niet al te goed doordacht is.
Antwoord 11
We moeten deze twee soorten uitzonderingen onderscheiden op basis van of het een programmeerfout is of niet.
- Als een fout een programmeerfout is, moet het een niet-aangevinkte uitzondering zijn.Bijvoorbeeld:
SQLException/IOException/NullPointerException. Deze uitzonderingen zijn:
programmeer fouten. Ze moeten worden afgehandeld door de programmeur. Terwijl in
JDBC API, SQLException is aangevinkt uitzondering, in het voorjaar JDBCTemplate
het is een ongecontroleerde uitzondering. Programmeur maakt zich geen zorgen over
SqlException, bij gebruik van Spring. - Als een fout geen programmeerfout is en de reden van buiten komt, moet het een gecontroleerde uitzondering zijn.Bijvoorbeeld: als de
bestand is verwijderd of de bestandsmachtiging is gewijzigd door iemand anders, It
moet worden hersteld.
FileNotFoundException is een goed voorbeeld om subtiele verschillen te begrijpen. FileNotFoundException wordt gegenereerd als het bestand niet wordt gevonden. Er zijn twee redenen voor deze uitzondering. Als het bestandspad is gedefinieerd door de ontwikkelaar of van de eindgebruiker is genomen via de GUI, moet dit een niet-aangevinkte uitzondering zijn. Als het bestand door iemand anders wordt verwijderd, moet het een gecontroleerde uitzondering zijn.
Aangevinkte uitzondering kan op twee manieren worden afgehandeld. Deze gebruiken try-catch of propageren de uitzondering. In het geval van verspreiding van een uitzondering, zullen alle methoden in de aanroepstack strak gekoppeldzijn vanwege het afhandelen van uitzonderingen. Daarom moeten we de gecontroleerde uitzondering zorgvuldig gebruiken.
In het geval dat u een gelaagd bedrijfssysteem ontwikkelt, moet u overwegend ongecontroleerde uitzonderingen te kiezen om te gooien, maar vergeet niet om gecontroleerde uitzonderingen te gebruiken voor het geval u niets kunt doen.
Antwoord 12
Aangevinkte uitzonderingen zijn handig voor herstelbare gevallen waarin u informatie aan de beller wilt verstrekken (d.w.z. onvoldoende rechten, bestand niet gevonden, enz.).
Niet-aangevinkte uitzonderingen worden zelden of helemaal niet gebruikt om de gebruiker of programmeur te informeren over ernstige fouten of onverwachte omstandigheden tijdens runtime. Gooi ze niet als je code of bibliotheken schrijft die door anderen zullen worden gebruikt, omdat ze misschien niet verwachten dat je software ongecontroleerde uitzonderingen genereert, omdat de compiler ze niet dwingt om te worden gevangen of gedeclareerd.
Antwoord 13
Als een uitzondering minder waarschijnlijk wordt verwacht, en we kunnen doorgaan, zelfs nadat we die hebben opgevangen, en we kunnen niets doen om die uitzondering te vermijden, dan kunnen we gecontroleerde uitzondering gebruiken.
Telkens wanneer we iets zinvols willen doen wanneer een bepaalde uitzondering zich voordoet en wanneer die uitzondering wordt verwacht maar niet zeker is, kunnen we gecontroleerde uitzondering gebruiken.
Telkens wanneer een uitzondering in verschillende lagen navigeert, hoeven we deze niet in elke laag op te vangen. In dat geval kunnen we runtime-uitzondering gebruiken of uitzondering inpakken als niet-aangevinkte uitzondering.
Runtime-uitzondering wordt gebruikt wanneer de kans het grootst is dat de uitzondering optreedt, er geen manier is om verder te gaan en niets kan worden hersteld. Dus in dit geval kunnen we voorzorgsmaatregelen nemen met betrekking tot die uitzondering. EX: NUllPointerException, ArrayOutofBoundsException. Deze komen vaker voor. In dit scenario kunnen we voorzorgsmaatregelen nemen tijdens het coderen om een dergelijke uitzondering te voorkomen. Anders moeten we overal try-catch-blokken schrijven.
Meer algemene uitzonderingen kunnen worden uitgeschakeld, minder algemene uitzonderingen worden aangevinkt.
Antwoord 14
Ik denk dat we uitzonderingen op verschillende vragen kunnen bedenken:
waarom gebeurt er een uitzondering? Wat kunnen we doen als het gebeurt
per ongeluk een bug.zoals een methode van een null-object wordt aangeroepen.
String name = null;
... // some logics
System.out.print(name.length()); // name is still null here
Dit soort uitzondering moet tijdens de test worden opgelost. Anders verbreekt het de productie en heb je een zeer hoge bug die onmiddellijk moet worden verholpen. Dit soort uitzonderingen hoeven niet gecontroleerd te worden.
door externe invoerkunt u de uitvoer van externe services niet controleren of vertrouwen.
String name = ExternalService.getName(); // return null
System.out.print(name.length()); // name is null here
Hier moet u mogelijk controleren of de naam null is als u wilt doorgaan wanneer deze null is, anders kunt u het met rust laten en het stopt hier en geeft de beller de runtime-uitzondering.
Dit soort uitzonderingen hoeven niet te worden gecontroleerd.
door runtime-uitzondering van extern,kunt u de externe service niet controleren of vertrouwen.
Hier moet u mogelijk alle uitzonderingen van ExternalService opvangen als u door wilt gaan wanneer het gebeurt, anders kunt u het met rust laten en het stopt hier en geeft de beller de runtime-uitzondering.
bij gecontroleerde uitzondering van extern,kunt u de externe service niet controleren of vertrouwen.
Hier moet u mogelijk alle uitzonderingen van ExternalService opvangen als u door wilt gaan wanneer het gebeurt, anders kunt u het met rust laten en het stopt hier en geeft de beller de runtime-uitzondering.
Moeten we in dit geval weten wat voor soort uitzondering er is opgetreden in ExternalService?Het hangt ervan af:
-
als je sommige soorten uitzonderingen aankunt, moet je ze opvangen en verwerken. Voor anderen, bubbel ze.
-
als je een log of reactie op de specifieke uitzondering nodig hebt, kun je ze opvangen. Voor anderen, bubbel ze.
Antwoord 15
Ik denk dat bij het declareren van Application Exception het een Unchecked Exception moet zijn, d.w.z. een subklasse van RuntimeException.
De reden is dat het de applicatiecode niet zal overladen met try-catch en throws-declaraties op methode. Als uw toepassing Java Api gebruikt die gecontroleerde uitzonderingen genereert die hoe dan ook moeten worden afgehandeld. In andere gevallen kan de toepassing een ongecontroleerde uitzondering genereren. Als de toepassingsaanroeper nog steeds niet-aangevinkte uitzonderingen moet afhandelen, kan dit worden gedaan.
Antwoord 16
De regel die ik gebruik is: gebruik nooit ongecontroleerde uitzonderingen! (of wanneer je er geen weg omheen ziet)
Vanuit het oogpunt van de ontwikkelaar die uw bibliotheek gebruikt of de eindgebruiker die uw bibliotheek/toepassing gebruikt, is het echt balen om geconfronteerd te worden met een toepassing die crasht vanwege een onbekende uitzondering. En rekenen op een catch-all is ook niet goed.
Op deze manier kan de eindgebruiker toch een foutmelding krijgen, in plaats van dat de applicatie volledig verdwijnt.