Kotlin From Scratch gestione delle eccezioni

Kotlin è un linguaggio di programmazione moderno che viene compilato in bytecode Java. È gratuito e open source e rende ancora più divertente la programmazione per Android.  

Nell'articolo precedente, hai imparato di più sulla programmazione orientata agli oggetti scavando in classi astratte, interfacce, ereditarietà e tipi di alias in Kotlin. 

In questo post continuerai a conoscere la programmazione in Kotlin imparando le eccezioni e come gestirle. 

1. Gestione delle eccezioni

Le eccezioni vengono utilizzate per indicare un problema nel nostro codice durante l'esecuzione di un programma. La gestione delle eccezioni è la capacità di affrontare (o gestire) l'eccezione che potrebbe verificarsi. Se non gestiamo alcuna eccezione che si verifica, il nostro programma interromperà immediatamente l'esecuzione della nostra app. 

La gestione delle eccezioni consente al nostro programma di continuare l'esecuzione anche in presenza di un'eccezione (sebbene sia altamente raccomandato registrare le eccezioni e segnalarle utilizzando uno strumento di segnalazione degli arresti anomali come Crashlytics).   

In Java, abbiamo due tipi di eccezioni: selezionata e deselezionata. Li spiegherò brevemente entrambi, ma inizieremo con le eccezioni non controllate. 

Eccezioni non selezionate

Queste sono eccezioni che vengono lanciate a causa di difetti nel codice. Sono una sottoclasse diretta o indiretta del RuntimeException superclasse. 

Esempi di eccezioni non controllate includono:

  • ArithmeticException: lanciato quando dividi per zero.
  • ArrayIndexOutOfBoundExceptions: lanciato quando si accede a un array con un indice illegale. 
  • SecurityException: lanciato dal responsabile della sicurezza per indicare una violazione della sicurezza.
  • NullPointerException: generato quando si richiama un metodo o una proprietà su un oggetto nullo.

Un metodo che potrebbe generare un'eccezione non controllata non contiene alcuna informazione sull'eccezione generata nella dichiarazione del suo metodo. 

public Integer divideByZero (numeratore intero, denominatore intero) numeratore / denominatore di ritorno;  divideByZero (7, 0) // genera ArithmeticException

Questi tipi di eccezione possono essere prevenuti con la codifica corretta. Nel codice sopra, dovremmo controllare se il denominatore era zero prima di eseguire l'operazione. Per queste eccezioni, lo sviluppatore non ha bisogno di intercettare l'eccezione usando il prova a prendere bloccare. In altre parole, non siamo costretti dal compilatore a racchiudere il codice che potrebbe attivare l'eccezione in a prova a prendere bloccare. Invece, dovremmo semplicemente assicurarci che le eccezioni non si verifichino mai in primo luogo.

Inoltre, ricorda, Kotlin è un linguaggio sicuro. In altre parole, può aiutarci a evitare di ottenere NullPointerExceptions nel nostro codice. Puoi leggere i post di Nullability, Loops e Conditions per ottenere un ripasso sulla sicurezza nulla in Kotlin. 

Eccezioni controllate in Java

Un metodo che potrebbe lanciare un'eccezione controllata deve dichiararlo nella sua firma del metodo usando getta parola chiave. Se chiami un metodo che genera un'eccezione controllata, devi o lanciarlo di nuovo dalla tua funzione o prenderlo e gestirlo usando un prova a prendere bloccare. 

Le eccezioni controllate sono eccezioni che vengono verificate in fase di compilazione. Questi tipi di eccezioni ereditano dal Eccezione classe. Un esempio di questo tipo di eccezione è IOException. Ciò può verificarsi quando si tenta di accedere a un file che non può essere aperto perché non esiste. (FileNotFoundException è una sottoclasse di IOException.)

// esegue in un thread in background public void editFile (File file, String text) try file.getParentFile (). mkdirs (); FileOutputStream fileOutputStream = new FileOutputStream (file); Writer writer = new BufferedWriter (new OutputStreamWriter (fileOutputStream)); prova writer.write (testo); writer.flush (); fileOutputStream.getFD () sync ().;  finally writer.close ();  catch (IOException e) // Registra l'eccezione e.printStackTrace (); 

Nel codice precedente, abbiamo usato a prova a prendere blocco per gestire il IOException dentro il editFile () metodo. Possiamo ora chiamare il editFile () metodo come normale, e il compilatore non si lamenterà. 

editFile (new File (""), "my text");

Guardando il codice qui sotto, abbiamo refactored il metodo per utilizzare invece il getta parola chiave nella firma del metodo. Questo indica ai chiamanti che devono gestire l'eccezione IOException che potrebbe essere lanciato quando si chiama il metodo editFile ().

// questo dovrebbe essere in un thread in background public void editFile (File file, String text) genera IOException file.getParentFile (). mkdirs (); FileOutputStream fileOutputStream = new FileOutputStream (file); Writer writer = new BufferedWriter (new OutputStreamWriter (fileOutputStream)); prova writer.write (testo); writer.flush (); fileOutputStream.getFD () sync ().;  finally writer.close (); 

Per chiamare il metodo sopra, dobbiamo circondarlo in a prova a prendere blocco per gestire l'eccezione.

prova editFile (new File (""), "my text");  catch (IOException e) e.printStackTrace (); 

Questa è stata una breve panoramica delle eccezioni in Java. Vediamo ora come Kotlin gestisce le eccezioni. 

2. Eccezioni in Kotlin

La principale differenza tra i meccanismi di eccezione di Kotlin e Java è che tutte le eccezioni sono deselezionate in Kotlin. In altre parole, non sono dichiarati esplicitamente nelle firme delle funzioni, come in Java.

fun editFile (file: File, text: String) file.parentFile.mkdirs () val fileOutputStream = FileOutputStream (file) val writer = BufferedWriter (OutputStreamWriter (fileOutputStream)) prova writer.write (testo) writer.flush () fileOutputStream .fd.sync () finally writer.close ()

Qui, abbiamo convertito il editFile () metodo per una funzione di Kotlin. Puoi vedere che la funzione non ha il genera IOException dichiarazione nella sua firma di funzione. getta non è nemmeno una parola chiave in Kotlin. 

Inoltre, possiamo chiamare questa funzione senza circondarla di prova a prendere block-e il compilatore non si lamenterà. In altre parole, non esistono eccezioni controllate in Kotlin. Tutte le eccezioni sono deselezionate. (Si noti che se viene lanciata un'eccezione, l'esecuzione del programma si interromperà normalmente). 

Se pensiamo che questa eccezione potrebbe sorgere, dovremmo comunque gestirla circondando il metodo con a prova a prendere blocco - ma questo non è applicato dal compilatore Kotlin. 

prova editFile (File (""), "testo 123") catch (e: IOException) e.printStackTrace ()

Se l'eccezione gettata all'interno del editFile () la funzione è un'istanza di IOException classe, la nostra catturare il blocco verrà eseguito e stamperemo semplicemente la traccia dello stack a scopo di debug.

Il prova a prendere Bloccare

Il provare costruire con catturare e finalmente le clausole in Kotlin sono simili a quelle di Java. 

fun foo () try throw Exception ("Exception message") catch (e: Exception) println ("Exception handled") finally println ("all'interno di finally block")

Qui, stiamo lanciando un Eccezione oggetto dentro il provare bloccare. Si noti che non abbiamo incluso il nuovo parola chiave come facciamo in Java per creare una nuova istanza. Si noti inoltre che non è stata specificata l'eccezione che verrà generata nella firma della funzione come dovremmo fare in Java. 

Gestiamo tutte le sottoclassi e le classi di tipi Eccezione nel blocco di cattura. L'opzionale finalmente il blocco viene sempre eseguito; in questo caso, normalmente chiudiamo tutte le risorse o le connessioni precedentemente aperte in modo da evitare perdite di risorse. Ad esempio, se apri un file o crei un database o una connessione di rete in a provare blocco, dovresti chiuderlo o liberarlo in a finalmente bloccare. 

Si noti che in Kotlin il gettare costrutto è un'espressione e può combinarsi con altre espressioni.

val letter = 'c' val result = if (lettera in 'a' ... 'z') lettera else throw IllegalArgumentException ("Una lettera deve essere compresa tra dalla a alla z") 

Anche il provare il costrutto può essere usato come espressione.

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

Qui, abbiamo assegnato il valore restituito da prova a prendere bloccare al risultato variabile. Se il numero non lo è 1, getta un IllegalArgumentException e il catturare il blocco viene eseguito. Il falso espressione nel catturare il valore del blocco verrà assegnato al risultato variabile. Se il numero è 1 invece, poi il vero il valore dell'espressione verrà assegnato al risultato variabile.

Interoperabilità Java

Le eccezioni in Kotlin si comportano normalmente in Java, ma voglio renderti conto di un'utile annotazione chiamata @throws a Kotlin che potrebbe tornare utile. Poiché tutte le eccezioni in Kotlin sono deselezionate, gli sviluppatori che consumano il codice Kotlin da Java potrebbero non sapere che le tue funzioni generano eccezioni. Tuttavia, è comunque possibile aggiungere le possibili eccezioni che potrebbero essere generate con una firma del metodo con @Gettare annotazione. Ciò avviserà i chiamanti Java di aver bisogno di gestire l'eccezione. 

Vediamo un esempio pratico di questa annotazione.

/ * File Functions.kt * / fun addNumberToTwo (a: Any): Int if (a! Is Int) throw IllegalArgumentException ("Il numero deve essere un numero intero") return 2 + a

Qui, abbiamo definito una funzione di Kotlin che può generare un'eccezione IllegalArgumentException solo se il tipo passato alla funzione non è di tipo Int

Chiamiamo questa funzione di alto livello addNumberToTwo () direttamente da Java nel modo seguente:

public void myJavaMethod () Intero risultato = FunctionsKt.addNumberToTwo (5); System.out.println (risultato); // 7

Questo funziona bene; il compilatore non si lamenta. Tuttavia, se vogliamo comunicare con i chiamanti Java che il addNumberToTwo () la funzione di primo livello genera un'eccezione, semplicemente aggiungiamo il @throws annotazione alla firma della funzione. 

@Throws (IllegalArgumentException :: class) fun addNumberToTwo (a: Any): Int if (a! Is Int) throw IllegalArgumentException ("Il numero deve essere un numero intero") return 2 + a

Questo @throws l'annotazione può accettare un elenco separato da virgole di argomenti di classi di eccezioni. Nel codice sopra, abbiamo appena incluso una classe di eccezione-IllegalArgumentException

Ora dobbiamo aggiornare il nostro codice Java per gestire l'eccezione.

public void myJavaMethod () genera IllegalArgumentException Integer result = FunctionsKt.addNumberToTwo (5); System.out.println (risultato); 

Se decompiliamo il Kotlin addNumberToTwo () funzione, usando il Mostra Kotlin Bytecode funzione (se sei in IntelliJ IDEA o Android Studio, usa Utensili > Kotlin Mostra Kotlin Bytecode), vedremo il seguente codice Java:

// ... public static final int addNumberToTwo (@NotNull Object a) genera IllegalArgumentException Intrinsics.checkParameterIsNotNull (a, "a"); if (! (a instanceof Integer)) throw (Throwable) (new IllegalArgumentException ("Number deve essere un numero intero"));  else return 2 + ((Number) a) .intValue ();  // ... 

Nel codice Java generato sopra (alcuni elementi del codice generato sono stati rimossi per brevità), puoi vedere che il compilatore ha aggiunto il getta parola chiave alla firma del metodo, perché abbiamo incluso il @throws annotazione. 

Conclusione

In questo tutorial, hai imparato di più sulla programmazione in Kotlin esaminando le eccezioni. Abbiamo visto che Kotlin non ha verificato le eccezioni ma che, invece, tutte le eccezioni sono deselezionate. Abbiamo anche esaminato come gestire le eccezioni usando il prova a prendere bloccare e ha visto l'utilità del @throws annotazione in Kotlin per i chiamanti Java. 

Per saperne di più sulla lingua di Kotlin, ti consiglio di visitare la documentazione di Kotlin. Oppure guarda alcuni dei nostri altri post di sviluppo di app per Android qui su Envato Tuts!