Kotlin From Scratch Exception Handling

Kotlin is een moderne programmeertaal die compileert met Java bytecode. Het is gratis en open source en maakt het coderen voor Android nog leuker.  

In het vorige artikel heb je meer geleerd over objectgeoriënteerd programmeren door je te verdiepen in abstracte klassen, interfaces, overerving en typaliassen in Kotlin. 

In dit bericht blijf je leren over programmeren in Kotlin door te leren over uitzonderingen en hoe je ermee om moet gaan. 

1. Afhandeling van uitzonderingen

Uitzonderingen worden gebruikt om een ​​probleem in onze code aan te geven tijdens de uitvoering van een programma. Behandeling van uitzonderingen is de mogelijkheid om de uitzondering die kan optreden, aan te pakken (of af te handelen). Als we niet omgaan met een uitzondering die optreedt, stopt ons programma abrupt en wordt onze app onmiddellijk gecrasht. 

Met uitzondering van de verwerking kan ons programma doorgaan met de uitvoering, zelfs als er een uitzondering is (hoewel het ten zeerste wordt aanbevolen om uw uitzonderingen te registreren en ze te rapporteren met behulp van een crashrapportagetool zoals Crashlytics).   

In Java hebben we twee soorten uitzonderingen: aangevinkt en uitgeschakeld. Ik zal ze in het kort uitleggen, maar we beginnen met ongecontroleerde uitzonderingen. 

Niet-gecontroleerde uitzonderingen

Dit zijn uitzonderingen die worden gegenereerd vanwege gebreken in uw code. Ze zijn een directe of indirecte subklasse van de RuntimeException superklasse. 

Voorbeelden van niet-gecontroleerde uitzonderingen zijn onder meer:

  • ArithmeticException: gegooid als je deelt door nul.
  • ArrayIndexOutOfBoundExceptions: gegooid wanneer een array is benaderd met een illegale index. 
  • Beveiligingsuitzondering: gegooid door de beveiligingsmanager om een ​​beveiligingsschending aan te geven.
  • NullPointerException: gegooid bij het aanroepen van een methode of eigenschap op een null-object.

Een methode die een ongecontroleerde uitzondering kan weggooien, bevat geen informatie over de uitzondering die is gegenereerd op de methode-declaratie. 

public Integer divideByZero (Integer-teller, geheel getal-noemer) return-teller / noemer;  divideByZero (7, 0) // gooit ArithmeticException

Deze soorten uitzonderingen kunnen worden voorkomen door rechts te coderen. In de bovenstaande code hadden we moeten controleren of de noemer nul was voordat de bewerking werd uitgevoerd. Voor deze uitzonderingen hoeft de ontwikkelaar de uitzondering met behulp van de. Niet te vangen proberen te vangen blok. Met andere woorden, we worden niet door de compiler gedwongen om de code in te pakken die de uitzondering in a zou kunnen veroorzaken proberen te vangen blok. In plaats daarvan moeten we er alleen voor zorgen dat de uitzonderingen nooit voorkomen.

Onthoud ook dat Kotlin een ongeldige veilige taal is. Met andere woorden, het kan ons helpen voorkomen dat we het krijgen NullPointerExceptions in onze code. Je kunt het bericht Nullability, Loops and Conditions lezen om een ​​opfrissing te krijgen over de nulveiligheid in Kotlin. 

Gecontroleerde uitzonderingen in Java

Een methode die een gecontroleerde uitzondering kan werpen, moet dit in de methodehandtekening declareren met behulp van de worpen trefwoord. Als u een methode aanroept die een gecontroleerde uitzondering genereert, moet u deze opnieuw uit uw functie gooien of deze vangen en verwerken met een proberen te vangen blok. 

Gecontroleerde uitzonderingen zijn uitzonderingen die tijdens het compileren worden gecontroleerd. Dit soort uitzonderingen erven van de Uitzondering klasse. Een voorbeeld van dit soort uitzonderingen is IOException. Dit kan gebeuren wanneer u toegang probeert te krijgen tot een bestand dat niet kan worden geopend omdat het niet bestaat. (FileNotFoundException is een subklasse van IOException.)

// uitvoeren in een achtergrondthread public void editFile (bestandsbestand, reekstekst) try file.getParentFile (). mkdirs (); FileOutputStream fileOutputStream = nieuwe FileOutputStream (bestand); Writer writer = new BufferedWriter (nieuwe OutputStreamWriter (fileOutputStream)); probeer writer.write (tekst); writer.flush (); fileOutputStream.getFD () sync ().;  eindelijk writer.close ();  catch (IOException e) // Registreer de uitzondering e.printStackTrace (); 

In de voorgaande code hebben we een proberen te vangen blok om de IOException binnen in de editFile () methode. We kunnen nu de editFile () methode als normaal, en de compiler zal niet klagen. 

editFile (nieuw bestand (""), "mijn tekst");

Als we naar de onderstaande code kijken, hebben we de methode opnieuw beschreven om in plaats daarvan de. Te gebruiken worpen sleutelwoord in de methodesignatuur. Dit geeft bellers aan dat ze met de uitzondering moeten omgaan IOException dat zou kunnen worden gegooid bij het aanroepen van de methode editFile ().

// dit zou in een thread op de achtergrond openbaar moeten zijn void editFile (Bestandsbestand, String-tekst) gooit IOException file.getParentFile (). mkdirs (); FileOutputStream fileOutputStream = nieuwe FileOutputStream (bestand); Writer writer = new BufferedWriter (nieuwe OutputStreamWriter (fileOutputStream)); probeer writer.write (tekst); writer.flush (); fileOutputStream.getFD () sync ().;  eindelijk writer.close (); 

Om de bovenstaande methode te gebruiken, moeten we deze omringen in a proberen te vangen blokkeren om de uitzondering af te handelen.

probeer editFile (nieuw bestand (""), "mijn tekst");  catch (IOException e) e.printStackTrace (); 

Dit is een korte blik op uitzonderingen in Java geweest. Laten we nu kijken hoe Kotlin uitzonderingen hanteert. 

2. Uitzonderingen in Kotlin

Het belangrijkste verschil tussen Kotlin en Java-uitzonderingsmechanismen is dat alle uitzonderingen niet zijn aangevinkt in Kotlin. Met andere woorden, ze worden niet expliciet gedeclareerd in de handtekeningen van functies, omdat ze zich in Java bevinden.

fun editFile (bestand: Bestand, tekst: String) file.parentFile.mkdirs () val fileOutputStream = FileOutputStream (bestand) val writer = BufferedWriter (OutputStreamWriter (fileOutputStream)) try writer.write (text) writer.flush () fileOutputStream .fd.sync () eindelijk writer.close ()

Hier hebben we het editFile () methode voor een Kotlin-functie. U kunt zien dat de functie niet de gooit IOException verklaring in zijn functiehandtekening. worpen is zelfs geen sleutelwoord in Kotlin. 

We kunnen deze functie ook noemen zonder deze te omringen met de proberen te vangen block - en de compiler zal niet klagen. Met andere woorden, er zijn niet zoiets als gecontroleerde uitzonderingen in Kotlin. Alle uitzonderingen zijn uitgeschakeld. (Merk op dat als er een uitzondering wordt gegenereerd, de uitvoering van het programma zal stoppen zoals normaal.) 

Als we denken dat deze uitzondering kan optreden, moeten we dit nog steeds behandelen door de methode te omringen met een proberen te vangen blokkeren, maar dit wordt niet afgedwongen door de Kotlin-compiler. 

probeer editFile (Bestand (""), "tekst 123") catch (e: IOException) e.printStackTrace ()

Als de uitzondering in de editFile () functie is een instantie van de IOException klas, onze vangst blok wordt uitgevoerd en we printen het stapeltracé gewoon voor foutopsporingsdoeleinden.

De proberen te vangen Blok

De proberen bouwen met vangst en Tenslotte clausules in Kotlin is vergelijkbaar met die van Java. 

fun foo () try throw Exception ("Exception message") catch (e: Exception) println ("Exception treatled") finally println ("inside finally block")

Hier gooien we een Uitzondering object binnen de proberen blok. Merk op dat we de nieuwe sleutelwoord zoals we dat in Java doen om een ​​nieuw exemplaar te maken. Merk ook op dat we niet de uitzondering hebben opgegeven die in de handtekening van de functie wordt gegooid zoals we dat in Java zouden moeten doen. 

We behandelen alle subklassen en klassen van het type Uitzondering in het catch-blok. De optionele Tenslotte blok wordt altijd uitgevoerd - hier sluiten we meestal alle bronnen of verbindingen die eerder zijn geopend om te voorkomen dat bronnen lekken. Als u bijvoorbeeld een bestand opent of een database- of netwerkverbinding maakt in a proberen blok, je zou het moeten sluiten of bevrijden in a Tenslotte blok. 

Merk op dat in Kotlin de gooien construct is een uitdrukking en kan worden gecombineerd met andere uitdrukkingen.

val letter = 'c' val result = if (letter in 'a' ... 'z') letter else throw IllegalArgumentException ("Een letter moet tussen a en z staan") 

Ook de proberen construct kan als een uitdrukking worden gebruikt.

fun foo (getal: Int) val result = try if (number! = 1) throw IllegalArgumentException () true catch (e: IllegalArgumentException) false println (result) foo (2) // false

Hier hebben we de waarde toegekend die is geretourneerd door de proberen te vangen blokkeren voor de resultaat variabel. Als het nummer dat niet is 1, het gooit een IllegalArgumentException en de vangst blok wordt uitgevoerd. De vals uitdrukking in de vangst blokwaarde wordt toegewezen aan de resultaat variabel. Als het nummer is 1 in plaats daarvan, dan de waar expressiewaarde wordt toegewezen aan de resultaat veranderlijk.

Java-interoperabiliteit

Uitzonderingen in Kotlin gedragen zich als normaal in Java, maar ik wil u op de hoogte brengen van een nuttige annotatie genaamd @throws in Kotlin kan dat van pas komen. Omdat alle uitzonderingen in Kotlin zijn uitgeschakeld, zijn ontwikkelaars die uw Kotlin-code van Java gebruiken mogelijk niet op de hoogte van het feit dat uw functies uitzonderingen bevatten. U kunt echter nog steeds de mogelijke uitzonderingen toevoegen die mogelijk naar een methodehandtekening worden gegooid met de @Gooien annotatie. Hiermee worden Java-bellers gewaarschuwd dat ze de uitzondering moeten afhandelen. 

Laten we een praktisch voorbeeld van deze annotatie bekijken.

/ * Functions.kt file * / fun addNumberToTwo (a: Any): Int if (a! Is Int) throw IllegalArgumentException ("Number moet een geheel getal zijn") return 2 + a

Hier hebben we een Kotlin-functie gedefinieerd die een uitzondering kan opleveren IllegalArgumentException alleen als het type dat is doorgegeven aan de functie niet van het type is Int

We noemen deze functie op het hoogste niveau addNumberToTwo () rechtstreeks vanuit Java op de volgende manier:

public void myJavaMethod () Geheel getal result = FunctionsKt.addNumberToTwo (5); System.out.println (resultaat); // 7

Dit werkt prima; de compiler klaagt niet. Als we echter met Java-bellers willen communiceren dat het addNumberToTwo () functie op het hoogste niveau genereert een uitzondering, we voegen eenvoudigweg het @throws annotatie van de functiesignatuur. 

@Throws (IllegalArgumentException :: class) fun addNumberToTwo (a: Any): Int if (a! Is Int) throw IllegalArgumentException ("Number moet een geheel getal zijn") return 2 + a

Deze @throws annotatie kan een door komma's gescheiden lijst met argumenten van uitzonderingsklassen accepteren. In de bovenstaande code hebben we slechts één uitzonderingsklasse opgenomen-IllegalArgumentException

Nu moeten we onze Java-code bijwerken om de uitzondering aan te kunnen.

openbare ongeldig myJavaMethod () gooit IllegalArgumentException Geheel getal result = FunctionsKt.addNumberToTwo (5); System.out.println (resultaat); 

Als we de Kotlin decompileren addNumberToTwo () functie, met behulp van de Toon Kotlin Bytecode functie gebruiken (als u in IntelliJ IDEA of Android Studio bent Hulpmiddelen > Kotlin Toon Kotlin Bytecode), zullen we de volgende Java-code zien:

// ... public static final int addNumberToTwo (@NotNull Object a) gooit IllegalArgumentException Intrinsics.checkParameterIsNotNull (a, "a"); if (! (een instantie van Integer)) throw (Throwable) (new IllegalArgumentException ("Number moet een geheel getal zijn"));  else return 2 + ((Number) a) .intValue ();  // ... 

In de gegenereerde Java-code hierboven (sommige elementen van de gegenereerde code zijn omwille van de eenvoud verwijderd), kunt u zien dat de compiler de worpen sleutelwoord voor de methodehandtekening - omdat we de @throws aantekening. 

Conclusie

In deze tutorial leer je meer over programmeren in Kotlin door uitzonderingen te bestuderen. We hebben gezien dat Kotlin geen uitzonderingen heeft gecontroleerd, maar dat in plaats daarvan alle uitzonderingen zijn uitgeschakeld. We hebben ook gekeken hoe om te gaan met uitzonderingen met behulp van de proberen te vangen blokkeer en zag de bruikbaarheid van de @throws annotatie in Kotlin voor Java-bellers. 

Voor meer informatie over de Kotlin-taal, raad ik aan de Kotlin-documentatie te bezoeken. Of bekijk enkele van onze andere Android-apps voor app-ontwikkeling hier op Envato Tuts!