scala特质底层java实现(反编译)

1. 简介

在scala中,一个类只能单继承一个类,但是一个类却可以多继承特质。从内容上来看,抽象类和特质中包含的内容是完全一致的,都可以有属性、抽象方法、普通方法(有具体实现的方法)。那在底层java代码是如何实现特质的多继承的呢。

2. 反编译代码查看

2.1 特质中只包含抽象方法

2.1.1 特质Trait03 的scala代码

trait Trait03 {  
  def sayHi()  
}

2.1.2 反编译 Trait03.class 代码

public abstract interface Trait03 {
    public abstract void sayHi();
}

2.1.3 特质子类 sheep的scala代码

class sheep extends Trait03 {
  override def sayHi(): Unit = {
    println("say Hi~~~")
  }
}

2.1.4 特质子类sheep反编译 sheep.class 代码

public class sheep implements Trait03 {
    public void sayHi() {
        Predef..MODULE$.println("say Hi~~~");
    }
}

2.1.5 代码分析

当特质中只有抽象方法时,在java实现中,该特质会被编译为抽象接口 public abstract interface ,该接口中包含抽象方法。scala中继承了特质的子类,在java实现中是实现对应的抽象接口,然后实现其中的抽象方法。

2.2 特质中包含抽象方法和普通方法

2.2.1 特质Trait03 的scala代码

trait Trait03 {
  def sayHi()
  def sayHello(): Unit = {
    println("say Hello~~~")
  }
}

2.2.2 反编译 Trait03.class 和 Trait03$class.class 代码

public abstract interface Trait03 {
    public abstract void sayHi();
    public abstract void sayHello();
}
public abstract class Trait03$class {
    public static void sayHello(Trait03 $this) {
        Predef..MODULE$.println("say Hello~~~");
    }
    public static void $init$(Trait03 $this) {
    }
}

2.2.3 特质子类 sheep的scala代码

class sheep extends Trait03 {
  override def sayHi(): Unit = {
    println("say Hi~~~")
  }
}

2.2.4 特质子类sheep反编译 sheep.class 代码

public class sheep implements Trait03 {
    public void sayHello() {
        Trait03$class.sayHello(this);
    }
    public sheep() {
        Trait03$class.$init$(this);
    }
    public void sayHi() {
        Predef..MODULE$.println("say Hi~~~");
    }
}

2.2.5 代码分析

  1. 当特质中同时包含抽象方法和普通方法时,特质底层java实现会将其拆分为一个抽象接口 Trait03 和一个抽象类 Trait03$class 。
    1. 抽象类中包含特质中的普通方法,并且将其设置为静态方法,提供对应的具体实现。同时提供静态的初始化方法,参数类型为特质本身。该初始化方法实现为空,可能只是为了解决多线程安全问题(现在原因未知)?
    2. 抽象接口中包含特质中的抽象方法

2. 特质子类继承特质后,底层java的实现:

                1. 现特质的抽象接口,然后在内部实现抽象接口的抽象方法。

        2. 提供实现子类的主构造方法,内部调用特质对应的抽象类中的初始化方法,将子类本身作为参数进行传递。

        3. 对于特质中的普通方法,特质子类底层java提供同名方法,实际是调用抽象类对应的静态方法,将子类本身作为参数进行传递。

3. 总结

当特质同时包含抽象方法和普通方法时,底层java实现会将其拆分,将抽象方法放到对应的抽象接口中,将普通方法放到对应的抽象类中,并提供对应的静态方法实现。因此在scala中可以实现特质的多继承,其内部原因就是特质多继承只是底层java多实现其多个特质对应的抽象接口,而对于其普通方法,子类只是静态调用特质对应的抽象类中的静态方法。
        所以scala特质可以多继承,但是抽象类却不可以多继承,因为抽象类属于类。

发布了20 篇原创文章 · 获赞 47 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/u012443641/article/details/89947324