加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

反编译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的“版本”.
根据我的理解,B.m1只是覆盖A.m1??和公共java.lang.Object m1(java.lang.Object)属于A,不应该
在B班.

解决方法

这是一种合成桥接方法.

在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;.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读