反编译Scala代码:为什么派生类中有两个重写的方法?

现在编码

反编译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.m1public java.lang.Object m1(java.lang.Object)属于A而不应该在class中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;

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在两个派生类之间执行专用代码

当我有两个函数时,为什么编译器不显示错误,一个将基类作为参数,一个将派生类作为参数?

为什么派生类重写方法不应比Java中的基类更严格?

为什么在一个文件中有两个并行的类?

为什么在VsCode git中有两个源代码控件?

为什么基类指针指向基类中的纯虚方法而不是派生类中的重写方法?

为什么我在Eclipse中有两个名为Fragment的类?

C++ 两个派生类在其中具有彼此的对象(包括问题)

两个派生类在方法中返回彼此的类型

为什么将Scala随播对象编译为两个类(Java和.NET编译器)?

嗨...不应该 id_public 变量给出的结果为 81 和 86?为什么它为两个派生类占用不同的内存位置?

为什么laravel消息包中有两个相同的方法?

派生类中的重写方法

从派生类对象访问重写的方法

在派生类中调用重写的方法

CRTP:为什么在获取派生类的嵌套类型和嵌套方法之间有区别?

为什么派生类中的重写函数会隐藏基类的其他重载?

为什么Scala案例类会生成两个apply方法?

.htaccess中有两个冲突的重写

基类和该基类的派生类可以有一个共同的朋友类,它是这两个类的朋友吗?

基类和该基类的派生类可以有一个共同的朋友类,它是这两个类的朋友吗?

关于后缀toString方法,这两个Scala代码段之间有什么区别?

从两个在基类和派生类基类使用装饰

为什么此代码有两个不同的结果?

为什么“ this”指针在派生类和第一个基类中具有相同的值

为什么`this`在调用派生类对象时无法从基类方法访问派生类成员

为什么编译器只编译我的代码的前两个部分?

为什么C#对象类具有两个equals方法

反编译的Lua中有_UPVALUE0_个关键字是什么?