2017-10-24 7 views
10

私は具体的にはwhenのように、識別がはるかに明確になるようにします。しかし私は、これを行うことで私が紹介しているかもしれない「罰則」について懸念しています。簡単な条件のときに使用するKotlin

私は実際にバイトコードの専門家ではありませんが、同じ 'ロジック'の場合、when節はより多くのバイトコード操作を必要とします。 3つの異なるKotlin機能

package com.whatever 

fun method1(): String { 
    return if (BuildConfig.DEBUG) "something" else "else" 
} 

fun method2(): String { 
    return if (BuildConfig.DEBUG) { 
    "something" 
    } else { 
    "else" 
    } 
} 

fun method3(): String { 
    return when (BuildConfig.DEBUG) { 
    true -> "something" 
    else -> "else" 
    } 
} 

シンプルなファイルは、バイトコード生成

// access flags 0x19 
    public final static method1()Ljava/lang/String; 
    @Lorg/jetbrains/annotations/NotNull;() // invisible 
    L0 
    LINENUMBER 4 L0 
    GETSTATIC com/whatever/BuildConfig.DEBUG : Z 
    IFEQ L1 
    LDC "something" 
    GOTO L2 
    L1 
    LDC "else" 
    L2 
    ARETURN 
    L3 
    MAXSTACK = 1 
    MAXLOCALS = 0 

    // access flags 0x19 
    public final static method2()Ljava/lang/String; 
    @Lorg/jetbrains/annotations/NotNull;() // invisible 
    L0 
    LINENUMBER 8 L0 
    GETSTATIC com/whatever/BuildConfig.DEBUG : Z 
    IFEQ L1 
    L2 
    LINENUMBER 9 L2 
    LDC "something" 
    L3 
    GOTO L4 
    L1 
    LINENUMBER 11 L1 
    LDC "else" 
    L5 
    LINENUMBER 8 L5 
    L4 
    ARETURN 
    L6 
    MAXSTACK = 1 
    MAXLOCALS = 0 

    // access flags 0x19 
    public final static method3()Ljava/lang/String; 
    @Lorg/jetbrains/annotations/NotNull;() // invisible 
    L0 
    LINENUMBER 16 L0 
    GETSTATIC com/whatever/BuildConfig.DEBUG : Z 
    ISTORE 0 
    L1 
    LINENUMBER 17 L1 
    ILOAD 0 
    ICONST_1 
    IF_ICMPNE L2 
    L3 
    LDC "something" 
    GOTO L4 
    L2 
    LINENUMBER 18 L2 
    LDC "else" 
    L5 
    LINENUMBER 16 L5 
    L4 
    ARETURN 
    L6 
    MAXSTACK = 2 
    MAXLOCALS = 1 

誰かが、このコストがどのように重要な指摘することはできますか?そして、私たちは単純な操作のためにこのパターンから離れようとするべきですか?

おかげ

答えて

9

ここでの唯一の違いは、method3BuildConfig.DEBUG値は最初のローカル変数に格納されてしまうことです。バイトコードをJavaに逆コンパイルすると、次のように表示されます。

@NotNull 
    public static final String method2() { 
     return BuildConfig.DEBUG?"something":"else"; 
    } 

    @NotNull 
    public static final String method3() { 
     boolean var0 = BuildConfig.DEBUG; 
     return var0?"something":"else"; 
    } 

これはごくわずかです。


我々はif/else句を展開すると、我々は次のように構築することができます。

fun method4(a: Int): String { 
    if (a == 1) { 
     return "1" 
    } else if (a == 2) { 
     return "2" 
    } else if (a == 3) { 
     return "3" 
    } else { 
     return "4" 
    } 
} 

fun method5(a: Int): String { 
    when (a) { 
     1 -> return "1" 
     2 -> return "2" 
     3 -> return "3" 
     else -> return "4" 
    } 
} 

このため、逆コンパイルバイトコードは次のとおりです。

@NotNull 
public static final String method4(int a) { 
    return a == 1?"1":(a == 2?"2":(a == 3?"3":"4")); 
} 

@NotNull 
public static final String method5(int a) { 
    switch(a) { 
    case 1: 
    return "1"; 
    case 2: 
    return "2"; 
    case 3: 
    return "3"; 
    default: 
    return "4"; 
    } 
} 

このように、簡単なwhen文はつまるところJavaのswitchステートメントこれらの2つの比較については、'Why switch is faster than if'を参照してください。

+0

バイトコードにコンパイルしてJavaに再び逆コンパイルした後、 'when'節が' if'節になるのは面白いことです。私はいくつかのコンパイラの最適化がこのロジックのためにあると思います。答えをありがとう。 –

関連する問題