blog

Kotlinで例外を処理する

これは非常に一般的なJavaの例外キャッチ処理で、似たような最適化を見たことがあるはずです。しかし、私はまだ自分の洞察力を言いたい はい、または上記のコードは、コードの1〜4行の本体を読む方法にされて...

Aug 16, 2020 · 4 min. read
シェア

.まず例外について説明しましょう

日々の開発では例外処理に遭遇することは避けられませんが、まずはコードの一部を見てください:

 private void handleCustomMessage(TIMMessage timMessage, TIMElem elem) {
 TIMCustomElem timCustomElem = (TIMCustomElem) elem;
 byte[] bytes = timCustomElem.getData();
 String data = new String(bytes);
 Log.e(TAG, "" + data);
 try {
 TXMessage message = new Gson().fromJson(data, TXMessage.class);
 if (message != null) {
 message.setSenderId(timMessage.getSender());
 String groupId = timMessage.getConversation().getPeer();
 message.setGroupId(groupId);
 for (int i = listeners.size() - 1; i > -1; i--) {
 TXIMStateListener listener = listeners.get(i);
 listener.onReceiveCustomMessage(message);
 }
 }
 } catch (Exception e) {
 e.printStackTrace();
 }
 }

これは非常に一般的なJavaの例外処理で、 同様の最適化見たことがあるはずです。しかし、私はまだ彼ら自身の洞察を言いたいのです!

trycatchのコードブロックが悪いと、読み取りが中断されます。

そうです、上と同じコードです。同じレイアウト戦略と命名スタイルを持つメソッド本体内の1~4行のコードを読み、どの行でバグが発生したのかを考えながらロジックに没頭していたあなたの目の前に突然tryキーワードが現れ、「ここで例外が発生した」と突然促されます。それだけでなく、その後もコードがインデントされ続けるので、目玉の動きで注意が一瞬止まり、すぐに頭が追いつきますが、それでも中断してしまいます。それだけでなく、例外を処理するために一時変数を定義したり名前をつけたりすることもあり、余計なロジックが増えます。

どうしたらいいかわからない例外

言語例外が発生した場合、このシナリオをどのように処理するかを製品や業務に照会ることがありますが、業務側は言語例外の発生には無関心です。製品や運用側にはこのような例外を理解する術がないため、例外を処理する能力がなく、開発者がこのような例外を場当たり的に処理して催促することで、ユーザーに迷惑をかける可能性があります。

その結果、ロジック例外の開発者はタイムリーに例外を処理できない可能性があります。

上記のコードは、例外をキャッチした後に例外を処理しません。実際のシナリオでは、開発者がこのコードを呼び出すのは、目的の効果を得るために実行すべきロジックをプログラムに実行させるためだけであり、例外が発生したときにこのコードが正しく実行できなければ、実行されることはありません。

そのため、例外を定義する際には、呼び出し側が例外を気にする必要があるかどうかを考慮する必要があります。

.Kotlinの例外は

Kotlinでは、Javaのようにtrycatchを使って例外をキャッチすることも可能ですが、それだけならこの記事の存在意義はなく、Kotlin標準ライブラリの拡張関数を使うことで、trycatchのコードを非常に便利かつ簡単に書くことができます:

kotlin.runCatching { }

その代わりに、例外をスローするコードを内部で書くだけで、例外を潔く処理することができます:

/**
 * Calls the specified function [block] and returns its encapsulated result if invocation was successful,
 * catching any [Throwable] exception that was thrown from the [block] function execution and encapsulating it as a failure.
 */
@InlineOnly
@SinceKotlin("1.3")
public inline fun <R> runCatching(block: () -> R): Result<R> {
 return try {
 Result.success(block())
 } catch (e: Throwable) {
 Result.failure(e)
 }
}

ありませんがあなたは例外の結果を懸念している場合は、唯一の真または偽は、メソッドがラッパークラスの結果を返すことに注意してください、コードが正しく実行された場合、成功を返し、例外が失敗を返すように発生します:

 fun testTry(){
 val result = kotlin.runCatching { doSomeThings() }.isFailure
 val result1 = kotlin.runCatching { doSomeThings() }.isSuccess
 }
 
 @Throws
 fun doSomeThings():Exception{
 return NullPointerException()
 }

懸念の結果がNULLまたは非NULLの場合。

val result3 = kotlin.runCatching { doSomeThings() }.getOrNull()

懸念の結果が例外そのものである場合:

 val result3 = kotlin.runCatching { doSomeThings() }.getOrThrow()
 val result4 = kotlin.runCatching { doSomeThings() }.getOrElse { }

もし、懸念事項が例外そのものの結果とエラーのロジックコード、リソースの解放であれば、素直にtrycatchを書く必要があります。

Read next

Redis分散ロックの実装

日々の開発において、ロックを追加しなければならない場面に遭遇することは避けられません。例えば、商品の在庫を差し引く場合、まずデータベースから在庫を取り出し、在庫判定を行い、それから在庫を差し引かなければなりません。この操作の波は、明らかに原子性に沿っていません。コードブロックがロックされていない場合、並行性のため、売れすぎの問題につながりやすいです。私たちのシステムは、モノリシックアーキテクチャの場合は、ローカルロックを使用すると、問題を解決することができます。分散アーキテクチャの場合は、分散ロックを使用する必要があります。

Aug 16, 2020 · 7 min read