Kotlin är ett modernt programmeringsspråk som kompilerar till Java bytecode. Det är gratis och öppen källkod, och gör kodning för Android ännu roligare.
I den föregående artikeln lärde du dig mer om objektorienterad programmering genom att gräva i abstrakta klasser, gränssnitt, arv och typ alias i Kotlin.
I det här inlägget fortsätter du att lära dig om programmering i Kotlin genom att lära dig om undantag och hur du hanterar dem.
Undantag används för att indikera ett problem i vår kod under ett programs körning. Undantagshantering är förmågan att ta itu med (eller hantera) det undantag som kan uppstå. Om vi inte hanterar något undantag som uppstår, kommer vårt program att sluta att exekvera och kraschar vår app omedelbart.
Undantagshantering gör det möjligt för vårt program att fortsätta exekveringen även om det fanns ett undantag (men det rekommenderas att du loggar in dina undantag och rapporterar dem med hjälp av ett kraschrapporteringsverktyg som Crashlytics).
I Java har vi två typer av undantag: markerad och okontrollerad. Jag förklarar dem kortfattat, men vi börjar med obekanta undantag.
Det här är undantag som kastas på grund av brister i din kod. De är en direkt eller indirekt underklass av RuntimeException
superklass.
Exempel på okontrollerade undantag är:
ArithmeticException
: kastas när du delar upp med noll.ArrayIndexOutOfBoundExceptions
: kastas när en array har nåts med ett olagligt index. SecurityException
: kastas av säkerhetschefen för att ange en säkerhetsöverträdelse.NullPointerException
: kastas när man anropar en metod eller egenskap på ett nullobjekt.En metod som kan kasta ett obefogat undantag innehåller ingen information om det undantag som gjorts på metoddeklarationen.
public Integer divideByZero (Integer täljare, integer nämnare) retur täljare / nämnare; divideByZero (7, 0) // kaster AritmeticException
Dessa typer av undantag kan förebyggas genom att koda rätt. I koden ovan borde vi ha kontrollerat om nämnaren var noll innan du utförde operationen. För dessa undantag behöver utvecklaren inte fånga undantaget med hjälp av försök fånga
blockera. Med andra ord, vi är inte tvungna av kompilatorn att paketera koden som kan utlösa undantaget i a försök fånga
blockera. Istället bör vi bara se till att undantagen aldrig uppstår i första hand.
Kom också ihåg, Kotlin är ett null säkert språk. Det kan med andra ord hjälpa oss att undvika att få NullPointerExceptions
i vår kod. Du kan läsa Nullability, Loops och Conditions posten för att få en uppdatering på null säkerhet i Kotlin.
En metod som kan kasta ett kontrollerat undantag måste deklareras i sin metod signatur med hjälp av kastar
nyckelord. Om du ringer en metod som kastar ett kontrollerat undantag, måste du antingen kasta den igen från din funktion eller att fånga den och hantera den med hjälp av en försök fånga
blockera.
Kontrollerade undantag är undantag som kontrolleras vid sammanställningstiden. Sådana undantag ärva från Undantag
klass. Ett exempel på denna typ av undantag är IOException
. Det här kan inträffa när du försöker komma åt en fil som inte kan öppnas eftersom den inte existerar. (FileNotFoundException
är en underklass av IOException
.)
// utföra i en bakgrundstråd public void editFile (Filfil, Stringtext) försök file.getParentFile (). mkdirs (); FileOutputStream fileOutputStream = ny FileOutputStream (fil); Writer writer = new BufferedWriter (ny OutputStreamWriter (fileOutputStream)); försök writer.write (text); writer.flush (); fileOutputStream.getFD () synk ().; äntligen writer.close (); fånga (IOException e) // Logga in undantaget e.printStackTrace ();
I den föregående koden använde vi en försök fånga
blockera för att hantera IOException
inuti editFile ()
metod. Vi kan nu ringa editFile ()
Metod som vanligt, och kompilatorn kommer inte att klaga.
editFile (ny fil (""), "min text");
Titta på koden nedan har vi refactored metoden för att istället använda kastar
sökord i metodens signatur. Detta indikerar att ringer som de behöver hantera undantaget IOException
som kan kastas när man ringer metoden editFile ()
.
// detta borde vara i en bakgrundstråd public void editFile (filfil, strängtext) kasta IOException file.getParentFile (). mkdirs (); FileOutputStream fileOutputStream = ny FileOutputStream (fil); Writer writer = new BufferedWriter (ny OutputStreamWriter (fileOutputStream)); försök writer.write (text); writer.flush (); fileOutputStream.getFD () synk ().; äntligen writer.close ();
För att ringa metoden ovan måste vi omge den i en försök fånga
blockera för att hantera undantaget.
försök editFile (ny fil (""), "min text"); fånga (IOException e) e.printStackTrace ();
Detta har varit en kort titt på undantag i Java. Låt oss nu se hur Kotlin hanterar undantag.
Huvudskillnaden mellan mekanismerna Kotlin och Java är att alla undantag är okontrollerade i Kotlin. Med andra ord, de är inte uttryckligen deklarerade i funktions signaturerna, som de är i Java.
roligt editFile (fil: fil, text: String) file.parentFile.mkdirs () val fileOutputStream = FileOutputStream (fil) val writer = BufferedWriter (OutputStreamWriter (fileOutputStream)) försök writer.write (text) writer.flush () fileOutputStream .fd.sync () äntligen writer.close ()
Här har vi konverterat editFile ()
metod för en Kotlin-funktion. Du kan se att funktionen inte har kastar IOException
uttalande i dess funktions signatur. kastar
är inte ens ett nyckelord i Kotlin.
Vi kan också ringa den här funktionen utan att omge den med försök fånga
blockera och kompilatorn kommer inte att klaga. Det är med andra ord ingen sådan sak som kontrollerade undantag i Kotlin. Alla undantag är avmarkerade. (Observera att om ett undantag kastas, slutar programkörningen som vanligt.)
Om vi tror att detta undantag kan uppstå, bör vi fortfarande hantera det genom att omge metoden med a försök fånga
block-men detta verkställs inte av Kotlin-kompilatorn.
försök editFile (File (""), "text 123") fånga (e: IOException) e.printStackTrace ()
Om undantaget kastas inuti editFile ()
funktion är en förekomst av IOException
klass, vår fånga
blocket kommer att utföras, och vi skriver ut stapelspåret för debugging.
försök fånga
BlockeraDe Prova
konstruera med fånga
och till sist
klausulerna i Kotlin liknar den i Java.
(exception) println ("Exception-hanterad") äntligen println ("inside finally block")
Här kastar vi en Undantag
föremål inuti Prova
blockera. Observera att vi inte inkluderade ny
sökord som vi gör i Java för att skapa en ny instans. Observera också att vi inte angav det undantag som kommer att kastas i funktions signaturen som vi skulle behöva i Java.
Vi hanterar alla underklasser och klasser av typ Undantag
i fångstblocket. Den frivilliga till sist
block exekveras alltid-det här är där vi stänger vanligtvis eventuella resurser eller anslutningar som tidigare öppnades för att förhindra läckage av resurser. Om du till exempel öppnar en fil eller skapar en databas eller nätverksanslutning i en Prova
blockera, bör du stänga eller befria det i en till sist
blockera.
Observera att i Kotlin den kasta
konstruera är ett uttryck och kan kombinera med andra uttryck.
val brev = 'c' valresultat = om (bokstaven i 'a' ... 'z') bokstäver annars kasta IllegalArgumentException ("Ett brev måste vara mellan a till z")
Även Prova
konstruktion kan användas som ett uttryck.
roligt foo (tal: Int) valresultat = försök om (nummer! = 1) kasta IllegalArgumentException () true fångst (e: IllegalArgumentException) false println (resultat) foo (2) // false
Här tilldelade vi värdet returnerat från försök fånga
blockera till resultat
variabel. Om numret inte är det 1
, det kastar en IllegalArgumentException
och den fånga
blocket körs. De falsk
uttryck i fånga
blockvärdet kommer att tilldelas till resultat
variabel. Om numret är 1
istället då Sann
expressionsvärdet kommer att tilldelas till resultat
variabel.
Undantag i Kotlin beter sig som vanligt i Java, men jag vill göra dig medveten om en användbar anmärkning som heter @throws
i Kotlin som kan komma till nytta. Eftersom alla undantag i Kotlin är avmarkerade, kanske utvecklare som konsumerar din Kotlin-kod från Java kanske inte är medvetna om att dina funktioner slår undantag. Du kan dock fortfarande lägga till de möjliga undantagen som kan kastas till en metod signatur med @Kasta
anteckning. Detta kommer att varna Java-uppringare som de behöver för att hantera undantaget.
Låt oss se ett praktiskt exempel på denna anteckning.
/ * Functions.kt fil * / kul addNumberToTwo (a: Any): Int om (a! Är Int) kasta IllegalArgumentException ("Numret måste vara ett heltal") returnera 2 + a
Här definierade vi en Kotlin-funktion som kan ta ett undantag IllegalArgumentException
endast om typen som passerat till funktionen inte är av typen int
.
Vi kallar den här toppnivån addNumberToTwo ()
direkt från Java på följande sätt:
public void myJavaMethod () Integerresultat = FunktionerKt.addNumberToTwo (5); System.out.println (resultat); // 7
Det fungerar bra kompilatorn klagar inte. Men om vi vill kommunicera med Java-uppringare att addNumberToTwo ()
toppnivån fungerar ett undantag, vi lägger helt enkelt till @throws
annotering till funktions signaturen.
@Throws (IllegalArgumentException :: class) kul addNumberToTwo (a: Any): Int om (a! Är Int) kasta IllegalArgumentException ("Numret måste vara ett heltal") returnera 2 + a
Detta @throws
annotering kan acceptera en kommaseparerad lista över argument av undantagsklasser. I koden ovan inkluderade vi bara en undantagsklass-IllegalArgumentException
.
Nu måste vi uppdatera vår Java-kod för att hantera undantaget.
public void myJavaMethod () kastar IllegalArgumentException Integer result = FunctionsKt.addNumberToTwo (5); System.out.println (resultat);
Om vi dekompilerar Kotlin addNumberToTwo ()
funktion, med hjälp av Visa Kotlin Bytecode funktionen (om du är i IntelliJ IDEA eller Android Studio, använd Verktyg > Kotlin > Visa Kotlin Bytecode) ser vi följande Java-kod:
// ... offentliga statiska slutliga int addNumberToTwo (@NotNull Object a) kastar IllegalArgumentException Intrinsics.checkParameterIsNotNull (a, "a"); om (! (en instans av Integer)) kasta (Kastbar) (ny IllegalArgumentException ("Nummer måste vara ett heltal")); else return 2 + ((Number) a) .intValue (); // ...
I den genererade Java-koden ovan (vissa element i den genererade koden avlägsnades för korthetens skull) kan du se att kompilatorn lagt till kastar
sökord till metodens signatur - eftersom vi inkluderade @throws
anteckning.
I denna handledning lärde du dig mer om programmering i Kotlin genom att titta på undantag. Vi såg att Kotlin inte har kontrollerade undantag men att alla undantag istället är okontrollerade. Vi tittade också på hur man hanterar undantag med hjälp av försök fånga
blockera och se användbarheten av @throws
anteckning i Kotlin för Java-anropare.
För att lära mig mer om Kotlins språket rekommenderar jag att du besöker Kotlins dokumentation. Eller kolla in några av våra andra Android App-utvecklingsposter här på Envato Tuts!