lambda 代替回调函数的本质
package com.ssy
class Main2 {
companion object {
@JvmStatic
fun main(list: Array<String>) {
var view = View()
view.setOnClickListener(object : OnClickListener {
override fun onClick(view: View) {
println("触发了 onClick 方法 ${view.toString()}")
}
})
view.click()
var view2 = View2()
view2.setOnClickListener {
println("触发了 onClick 方法 $it")
}
view2.click()
}
}
}
class View {
var clickListener: OnClickListener? = null;
fun setOnClickListener(clickListener: OnClickListener) {
this.clickListener = clickListener;
}
fun click() {
clickListener?.onClick(this)
}
override fun toString(): String {
return "View"
}
}
//本质上是想传递onClick方法的,但是java不能传递方法,只能用对象来包裹,去传递
interface OnClickListener {
fun onClick(view: View)
}
class View2 {
var onClick: ((View2) -> Unit)? = null
fun click() {
onClick?.invoke(this@View2)
}
fun setOnClickListener(onClick: (View2) -> Unit) {
this.onClick = onClick
}
override fun toString(): String {
return "View2"
}
}
public final class Main2 {
@NotNull
public static final Companion Companion = new Companion((DefaultConstructorMarker) null);
@JvmStatic
public static final void main(@NotNull String[] list) {
Companion.main(list);
}
}
public final class Main2$Companion {
private Main2$Companion() {
}
public /* synthetic */ Main2$Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
@JvmStatic
public final void main(@NotNull String[] list) {
Intrinsics.checkNotNullParameter(list, "list");
View2 view2 = new View2();
view2.setOnClickListener(main.1.INSTANCE);
view2.click();
}
}
final class Main2$Companion$main$1 extends Lambda implements Function1<View2, Unit> {
public static final Main2$Companion$main$1 INSTANCE = new Main2$Companion$main$1();
Main2$Companion$main$1() {
super(1);
}
public /* bridge */ /* synthetic */ Object invoke(Object obj) {
invoke((View2) obj);
return Unit.INSTANCE;
}
public final void invoke(@NotNull View2 it) {
Intrinsics.checkNotNullParameter(it, "it");
System.out.println((Object) ("触发了 onClick 方法 " + it));
}
}
public final class View2 {
@Nullable
private Function1<? super View2, Unit> onClick;
/* JADX DEBUG: Type inference failed for r0v0. Raw type applied. Possible types: kotlin.jvm.functions.Function1<? super com.ssy.View2, kotlin.Unit>, kotlin.jvm.functions.Function1<com.ssy.View2, kotlin.Unit> */
@Nullable
public final Function1<View2, Unit> getOnClick() {
return this.onClick;
}
public final void setOnClick(@Nullable Function1<? super View2, Unit> function1) {
this.onClick = function1;
}
public final void click() {
Function1<? super View2, Unit> function1 = this.onClick;
if (function1 != null) {
Unit unit = (Unit) function1.invoke(this);
}
}
public final void setOnClickListener(@NotNull Function1<? super View2, Unit> function1) {
Intrinsics.checkNotNullParameter(function1, "onClick");
this.onClick = function1;
}
@NotNull
public String toString() {
return "View2";
}
}
通过查看反编译后的java源码,我们发现kotlin的这些便利,完全是语法糖去包装的。
通过黑魔法生成符合Jvm的代码。
所谓的传递方法,其实也是用对来包装的
我们来看看 Function1 是什么?原来就是一个
public interface Function1<in P1, out R> : Function<R> {
/** Invokes the function with the specified argument. */
public operator fun invoke(p1: P1): R
}
这里就设计到了 operator 操作符重载 () 相当于 invoke()
class ClickAction{
operator fun invoke(){
println("invoke~~~~~")
}
}
var click = ClickAction()
click()
> Task :Main2.main()
invoke~~~~~
package kotlin.jvm.functions
/** A function that takes 0 arguments. */
public interface Function0<out R> : Function<R> {
/** Invokes the function. */
public operator fun invoke(): R
}
/** A function that takes 1 argument. */
public interface Function1<in P1, out R> : Function<R> {
/** Invokes the function with the specified argument. */
public operator fun invoke(p1: P1): R
}
/** A function that takes 2 arguments. */
public interface Function2<in P1, in P2, out R> : Function<R> {
/** Invokes the function with the specified arguments. */
public operator fun invoke(p1: P1, p2: P2): R
}
/** A function that takes 3 arguments. */
public interface Function3<in P1, in P2, in P3, out R> : Function<R> {
/** Invokes the function with the specified arguments. */
public operator fun invoke(p1: P1, p2: P2, p3: P3): R
}
/** A function that takes 4 arguments. */
public interface Function4<in P1, in P2, in P3, in P4, out R> : Function<R> {
/** Invokes the function with the specified arguments. */
public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4): R
}
通过源码我们知道了,其实kotlin 的传递方法,也是通过我们熟悉的接口方式去实现。
首先他有个接口池,里面有各种参数的方法。通过编译器匹配到我们对应的接口和方法,通过编译代替我们去写模板,最后就是我们看到的了。
这里语法糖真的就是一个障眼法,给我们编程最大的方便,背后,它去通过模板生成我们平时要写的代码。
所以koltin是一门很实用的语言。尽可能减少我们编写的代码量,这样可以减少错误,也可以通过模板去规范我们平时不容易规范的编程习惯。
协程的真面目
kotlin 代码
class main3 {
companion object {
@JvmStatic
fun main(array: Array<String>) {
GlobalScope.launch {
println("${Thread.currentThread().id} ${Thread.currentThread().name}")
getData()
}
Thread.sleep(5000)
}
}
}
suspend fun getData() = withContext(Dispatchers.IO) {
delay(3000)
val cat = Cat("xiao", 1)
println("${Thread.currentThread().id} ${Thread.currentThread().name}")
cat
}
data class Cat(val name: String, val age: Int)
反编译后的java代码
1、data 类 Cat
public final class Cat {
private final int age;
@NotNull
private final String name;
public static /* synthetic */ Cat copy$default(Cat cat, String str, int i, int i2, Object obj) {
if ((i2 & 1) != 0) {
str = cat.name;
}
if ((i2 & 2) != 0) {
i = cat.age;
}
return cat.copy(str, i);
}
@NotNull
public final String component1() {
return this.name;
}
public final int component2() {
return this.age;
}
@NotNull
public final Cat copy(@NotNull String name2, int age2) {
Intrinsics.checkNotNullParameter(name2, "name");
return new Cat(name2, age2);
}
public boolean equals(@Nullable Object obj) {
if (this != obj) {
if (obj instanceof Cat) {
Cat cat = (Cat) obj;
if (!Intrinsics.areEqual(this.name, cat.name) || this.age != cat.age) {
return false;
}
}
return false;
}
return true;
}
public int hashCode() {
String str = this.name;
return ((str != null ? str.hashCode() : 0) * 31) + Integer.hashCode(this.age);
}
@NotNull
public String toString() {
return "Cat(name=" + this.name + ", age=" + this.age + ")";
}
public Cat(@NotNull String name2, int age2) {
Intrinsics.checkNotNullParameter(name2, "name");
this.name = name2;
this.age = age2;
}
public final int getAge() {
return this.age;
}
@NotNull
public final String getName() {
return this.name;
}
}
main3
public final class main3 {
@NotNull
public static final Companion Companion = new Companion((DefaultConstructorMarker) null);
@JvmStatic
public static final void main(@NotNull String[] array) {
Companion.main(array);
}
}
main3$Companion
public final class main3$Companion {
private main3$Companion() {
}
public /* synthetic */ main3$Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
@JvmStatic
public final void main(@NotNull String[] array) {
Intrinsics.checkNotNullParameter(array, "array");
BuildersKt.launch$default(GlobalScope.INSTANCE, (CoroutineContext) null, (CoroutineStart) null, new main.1((Continuation) null), 3, (Object) null);
Thread.sleep(5000);
}
}
final class main3$Companion$main$1 extends SuspendLambda implements Function2<CoroutineScope, Continuation<? super Unit>, Object> {
int label;
main3$Companion$main$1(Continuation continuation) {
super(2, continuation);
}
@NotNull
public final Continuation<Unit> create(@Nullable Object value, @NotNull Continuation<?> continuation) {
Intrinsics.checkNotNullParameter(continuation, "completion");
return new main3$Companion$main$1(continuation);
}
public final Object invoke(Object obj, Object obj2) {
return create(obj, (Continuation) obj2).invokeSuspend(Unit.INSTANCE);
}
@Nullable
public final Object invokeSuspend(@NotNull Object obj) {
Object coroutine_suspended = IntrinsicsKt.getCOROUTINE_SUSPENDED();
switch (this.label) {
case 0:
ResultKt.throwOnFailure(obj);
StringBuilder sb = new StringBuilder();
Thread currentThread = Thread.currentThread();
Intrinsics.checkNotNullExpressionValue(currentThread, "Thread.currentThread()");
StringBuilder append = sb.append(currentThread.getId()).append(" ");
Thread currentThread2 = Thread.currentThread();
Intrinsics.checkNotNullExpressionValue(currentThread2, "Thread.currentThread()");
System.out.println((Object) append.append(currentThread2.getName()).toString());
this.label = 1;
if (Main3Kt.getData(this) == coroutine_suspended) {
return coroutine_suspended;
}
break;
case 1:
ResultKt.throwOnFailure(obj);
break;
default:
throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
}
return Unit.INSTANCE;
}
}
public final class Main3Kt {
@Nullable
public static final Object getData(@NotNull Continuation<? super Cat> continuation) {
return BuildersKt.withContext(Dispatchers.getIO(), new getData.2((Continuation) null), continuation);
}
}
final class Main3Kt$getData$2 extends SuspendLambda implements Function2<CoroutineScope, Continuation<? super Cat>, Object> {
int label;
Main3Kt$getData$2(Continuation continuation) {
super(2, continuation);
}
@NotNull
public final Continuation<Unit> create(@Nullable Object value, @NotNull Continuation<?> continuation) {
Intrinsics.checkNotNullParameter(continuation, "completion");
return new Main3Kt$getData$2(continuation);
}
public final Object invoke(Object obj, Object obj2) {
return create(obj, (Continuation) obj2).invokeSuspend(Unit.INSTANCE);
}
@Nullable
public final Object invokeSuspend(@NotNull Object obj) {
Object coroutine_suspended = IntrinsicsKt.getCOROUTINE_SUSPENDED();
switch (this.label) {
case 0:
ResultKt.throwOnFailure(obj);
this.label = 1;
if (DelayKt.delay(3000, this) == coroutine_suspended) {
return coroutine_suspended;
}
break;
case 1:
ResultKt.throwOnFailure(obj);
break;
default:
throw new IllegalStateException("call to 'resume' before 'invoke' with coroutine");
}
Cat cat = new Cat("xiao", 1);
StringBuilder sb = new StringBuilder();
Thread currentThread = Thread.currentThread();
Intrinsics.checkNotNullExpressionValue(currentThread, "Thread.currentThread()");
StringBuilder append = sb.append(currentThread.getId()).append(" ");
Thread currentThread2 = Thread.currentThread();
Intrinsics.checkNotNullExpressionValue(currentThread2, "Thread.currentThread()");
System.out.println((Object) append.append(currentThread2.getName()).toString());
return cat;
}
}