scala里的静态代理(static-forwarders)

静态代理(static-forwarders)是编译器针对从java调用scala的object里的方法提供的一种便捷。

比如,我们如何在java中调用下面object里的foo方法?

$ cat A.scala 
object A {
  def foo() = 2
}

按照通常的逻辑,我们需要在java里获取到这个单例对象,然后通过这个对象调用foo方法,不过这样做的前提你需要了解object A这个单例编译后的字节码信息:

$ javap A$
Compiled from "A.scala"
public final class A$ {
  public static final A$ MODULE$;
  public static {};
  public int foo();
}

可以看到单例中有个MODULE$的静态成员,这个MODULE$就是A$的单实例,所以我们在java中可以通过这样的形式调用: A$.MODULE$.foo()

$ cat Test.java
public class Test {
    public static void main(String[] args) {
        System.out.println(A$.MODULE$.foo());
    }
}

$ javac -cp .:/data/tools/scala/lib/scala-library.jar Test.java

$ java Test
2 

上面的方式需要你了解单例对象编译后的细节,显然不够友好。所以为了对java调用的友好,scala编译器有个静态代理机制(static-forwarders),也就是会把object中的方法以静态方式在同名的class中生成一份。

依然看最开始定义的那个object A,在编译后,其实有2个class:A.class和A$.class
(scala中为了避免static的概念,引入了object,而object本质是一个模式语法糖,而非新的概念,最终在编译时都转换为java里的class)

那么看看A.class里有什么?

$ javap A
Compiled from "A.scala"
public final class A {
  public static int foo(); //一个静态foo方法
}

// 这个静态方式内部就是去找 A$.MODULE$ 然后在调用foo的 
public static int foo();
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=1, locals=0, args_size=0
         0: getstatic     #16                 // Field A$.MODULE$:LA$;
         3: invokevirtual #18                 // Method A$.foo:()I
         6: ireturn

它的目的就是为在java中调用单例对象中的方法提供方便,我们可以直接通过 A.foo()来调用

$ cat Test.java
public class Test {
    public static void main(String[] args) {
        System.out.println(A.foo());
    }
}

$ javac -cp .:/data/tools/scala/lib/scala-library.jar Test.java

$ java Test
2 

添加静态代理的过程在编译时是可以观察到的(打开log:jvm选项):

$ scalac -Ylog:jvm A.scala
[log jvm] Dumping mirror class for 'A'
[log jvm] Adding static forwarder for 'method foo' from A to 'object A'

对于伴生对象中的方法,一样会在伴生类中生成一份静态代理

原文:http://hongjiang.info/scala-static-forwarders/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值