2017-10-24 23 views
10

Tôi personaly giống như cú pháp when vì nó khiến cho định danh rõ ràng hơn nhiều. Tuy nhiên tôi lo ngại về 'các hình phạt' mà tôi có thể giới thiệu bằng cách làm điều này.Kotlin khi sử dụng trong điều kiện đơn giản

Tôi không thực sự là một chuyên gia về bytecode, nhưng tôi có thể thấy rằng đối với cùng một 'logic', mệnh đề khi có nhiều hoạt động bytecode hơn.

tập tin đơn giản với 3 chức năng khác nhau 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" 
    } 
} 

tạo bytecode

// 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 

Ai đó có thể chỉ ra cách đáng kể chi phí này là gì? Và chúng ta nên cố gắng tránh xa mô hình này cho các hoạt động đơn giản?

Cảm ơn

Trả lời

9

Sự khác biệt duy nhất ở đây là trong method3 giá trị BuildConfig.DEBUG được lưu trữ trong một biến địa phương đầu tiên. Khi dịch ngược mã byte sang Java, bạn sẽ thấy như sau:

@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"; 
    } 

Điều này là không đáng kể.


Nếu chúng ta mở rộng if/else khoản, chúng tôi có thể xây dựng như sau:

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" 
    } 
} 

Bytecode decompiled cho điều này là:

@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"; 
    } 
} 

Do đó, một tuyên bố đơn giản when sôi xuống một tuyên bố switch trong Java. Xem 'Why switch is faster than if' để so sánh giữa hai loại này.

+0

Điều thú vị là mệnh đề 'khi' trở thành mệnh đề' if' sau khi biên dịch thành bytecode và dịch ngược lại thành Java. Tôi đoán một số tối ưu hóa trình biên dịch được đặt ra cho logic này. Cảm ơn câu trả lời. –

Các vấn đề liên quan