JvmMultifile 註解在 Kotlin 中的應用

  • 2020 年 1 月 19 日
  • 筆記

接觸過Kotlin之後,我們會利用其擴展方法特性創建很多便捷的方法來實現更好更快的編碼。比如我們對於RxJava進行一些簡單的擴展方法實現。

下面的這段程式碼實現一個將任意的對象轉成Single實例

1 2 3 4 5 6 7 8 9 10 11

package com.example.jvmannotationsample import io.reactivex.Single //fileName:SingleExt.kt /** * shortcut method to change T instance into Single<T> instance */ fun <T: Any> T.toSingle(): Single<T> { return Single.just(this) }

接下來的程式碼,實現將任意類型的List轉成Observable實例

1 2 3 4 5 6 7 8 9 10

package com.example.jvmannotationsample import io.reactivex.Observable //fileName:ObservableExt.kt /** * shortcut method to convert List<T> instance to Observable<List<T>> instance */ fun <T: Any> List<T>.toObservable(): Observable<List<T>> { return Observable.fromArray(this) }

針對上面的程式碼,我們使用時會是下面的樣子

1 2 3

//the old way SingleExtKt.toSingle("Kotlin"); ObservableExtKt.toObservable(Arrays.asList("Kotlinc", "Developer", "Friends"));

能不能將上面兩個類合成一個呢

有時候,我們可能處於這樣的考慮,比如SingleExt與ObservableExt裡面的擴展方法都是和RxJava有關,可不可以同一稱為RxUtil呢,這樣使用起來也很方面。

答案是,可以的,就是利用@file:JvmName和@file:JvmMultifileClass就可以實現。

實現程式碼如下

1 2 3 4 5 6 7 8 9 10 11 12

@file:JvmName("RxUtil") @file:JvmMultifileClass package com.example.jvmannotationsample import io.reactivex.Single //fileName:SingleExt.kt /** * shortcut method to change T instance into Single<T> instance */ fun <T: Any> T.toSingle(): Single<T> { return Single.just(this) }

1 2 3 4 5 6 7 8 9 10 11 12

@file:JvmName("RxUtil") @file:JvmMultifileClass package com.example.jvmannotationsample import io.reactivex.Observable //fileName:ObservableExt.kt /** * shortcut method to convert List<T> instance to Observable<List<T>> instance */ fun <T: Any> List<T>.toObservable(): Observable<List<T>> { return Observable.fromArray(this) }

修改後,就可以在Java中完全使用RxUtil調用了。

1 2 3

//a much better way using @file:JvmMultifileClass RxUtil.toSingle("Kotlin"); RxUtil.toObservable(Arrays.asList("Kotlinc", "Developer", "Friends"));

內部機制

確實有一些神奇,簡簡單單的增加幾個註解,就能實現。但是這樣遠遠還不夠,我們需要了解它是如何工作的。

查找對應的類

1 2 3 4

find . -name "*.class" ./app/build/tmp/kotlin-classes/debug/com/example/jvmannotationsample/RxUtil.class ./app/build/tmp/kotlin-classes/debug/com/example/jvmannotationsample/RxUtil__ObservableExtKt.class ./app/build/tmp/kotlin-classes/debug/com/example/jvmannotationsample/RxUtil__SingleExtKt.class

使用javap工具拆解分析RxUtil.class文件

1 2 3 4 5 6 7 8 9 10 11 12 13 14

javap -c ./app/build/tmp/kotlin-classes/debug/com/example/jvmannotationsample/RxUtil.class public final class com.example.jvmannotationsample.RxUtil { public static final <T> io.reactivex.Observable<java.util.List<T>> toObservable(java.util.List<? extends T>); Code: 0: aload_0 1: invokestatic #12 // Method com/example/jvmannotationsample/RxUtil__ObservableExtKt.toObservable:(Ljava/util/List;)Lio/reactivex/Observable; 4: areturn public static final <T> io.reactivex.Single<T> toSingle(T); Code: 0: aload_0 1: invokestatic #21 // Method com/example/jvmannotationsample/RxUtil__SingleExtKt.toSingle:(Ljava/lang/Object;)Lio/reactivex/Single; 4: areturn }

上面的程式碼,我們可以看到

  • toObservable方法內部實際上是調用了RxUtil__ObservableExtKt.toObservable
  • toSingle 方法內部實際上是調用了RxUtil__SingleExtKt.toSingle

下面是對兩個具體實現類的分析。

使用javap工具拆解分析RxUtil__ObservableExtKt.class文件

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

javap -c ./app/build/tmp/kotlin-classes/debug/com/example/jvmannotationsample/RxUtil__ObservableExtKt.class Compiled from "ObservableExt.kt" final class com.example.jvmannotationsample.RxUtil__ObservableExtKt { public static final <T> io.reactivex.Observable<java.util.List<T>> toObservable(java.util.List<? extends T>); Code: 0: aload_0 1: ldc #10 // String $this$toObservable 3: invokestatic #16 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V 6: iconst_1 7: anewarray #18 // class java/util/List 10: dup 11: iconst_0 12: aload_0 13: aastore 14: invokestatic #24 // Method io/reactivex/Observable.fromArray:([Ljava/lang/Object;)Lio/reactivex/Observable; 17: dup 18: ldc #26 // String Observable.fromArray(this) 20: invokestatic #29 // Method kotlin/jvm/internal/Intrinsics.checkExpressionValueIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V 23: areturn }

使用javap工具拆解分析RxUtil__SingleExtKt.class文件

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

javap -c ./app/build/tmp/kotlin-classes/debug/com/example/jvmannotationsample/RxUtil__SingleExtKt Warning: Binary file ./app/build/tmp/kotlin-classes/debug/com/example/jvmannotationsample/RxUtil__SingleExtKt contains com.example.jvmannotationsample.RxUtil__SingleExtKt Compiled from "SingleExt.kt" final class com.example.jvmannotationsample.RxUtil__SingleExtKt { public static final <T> io.reactivex.Single<T> toSingle(T); Code: 0: aload_0 1: ldc #10 // String $this$toSingle 3: invokestatic #16 // Method kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V 6: aload_0 7: invokestatic #21 // Method io/reactivex/Single.just:(Ljava/lang/Object;)Lio/reactivex/Single; 10: dup 11: ldc #23 // String Single.just(this) 13: invokestatic #26 // Method kotlin/jvm/internal/Intrinsics.checkExpressionValueIsNotNull:(Ljava/lang/Object;Ljava/lang/String;)V 16: areturn }

相關Kotlin內容推薦