反编译Scala代码:为什么派生类中有两个重写方法?
发布时间:2020-12-16 08:59:03 所属栏目:安全 来源:网络整理
导读:反编译 Scala代码:为什么派生类中有两个重写方法? class A{ private var str: String = "A" val x: A = this override def toString(): String = str def m1(other: AnyRef): AnyRef = { println("This is A.m1(AnyRef)") other }}class B extends A { pri
反编译
Scala代码:为什么派生类中有两个重写方法?
class A { private var str: String = "A" val x: A = this override def toString(): String = str def m1(other: AnyRef): AnyRef = { println("This is A.m1(AnyRef)") other } } class B extends A { private var str: String = "B" var z: Int = 0 override val x: B = this override def m1(other: AnyRef): B = { println("This is B.m1(AnyRef)") this } } 上面代码的B类反编译为: public class test$B extends test$A { private java.lang.String str; private int z; private final test$B x; private java.lang.String str(); private void str_$eq(java.lang.String); public int z(); public void z_$eq(int); public test$B x(); public test$B m1(java.lang.Object); public java.lang.Object m1(java.lang.Object); public test$A x(); public test$B(); } 我无法理解为什么在反编译代码中有两个方法m1的“版本”. 解决方法
这是一种合成桥接方法.
在Java字节码中,方法仅覆盖具有完全相同签名的方法.如果B没有Object m1(Object)的任何实例,那么任何调用它的尝试都会调用A中的实现,这不是你想要的.因此,编译器插入一个简单地调用B m1(Object)的合成桥接方法.此行为并非特定于Scala – 它也发生在纯Java中. 您可以通过检查反汇编来更详细地查看它.如果我编译并反汇编以下代码 class A { def m1(other: AnyRef): AnyRef = { println("This is A.m1(AnyRef)") other } } class B extends A { override def m1(other: AnyRef): B = { println("This is B.m1(AnyRef)") this } } B的相关部分是 .method public m1 : (Ljava/lang/Object;)LB; .code stack 2 locals 2 L0: getstatic Field scala/Predef$MODULE$Lscala/Predef$; L3: ldc 'This is B.m1(AnyRef)' L5: invokevirtual Method scala/Predef$println (Ljava/lang/Object;)V L8: aload_0 L9: areturn L10: .end code .methodparameters other final .end methodparameters .end method .method public bridge synthetic m1 : (Ljava/lang/Object;)Ljava/lang/Object; .code stack 2 locals 2 L0: aload_0 L1: aload_1 L2: invokevirtual Method B m1 (Ljava/lang/Object;)LB; L5: areturn L6: .end code .methodparameters other final .end methodparameters .end method 如您所见,方法m1(Ljava / lang / Object;)Ljava / lang / Object;只需将参数转发给m1(Ljava / lang / Object;)LB;. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |