"new()"在"静态"内部做了什么,"静态"单独如何不抛出编译/运行错误?

Alp*_*ran 5 java decompiling scala

我做了一个非常简单的Scala程序,只打印Hello World:

object HelloWorldActivity {
    def main(args: Array[String]) {
        println("Hello, world")
    }
}
Run Code Online (Sandbox Code Playgroud)

为了理解Scala如何转换为Java字节码,我反编译了生成的jar文件,其中有两个文件:HelloWorldActivity.classHelloWorldActivity$.class.

第一个包含此代码:

import scala.reflect.ScalaSignature;

@ScalaSignature(bytes="****************")
public final class HelloWorldActivity
{
  public static void main(String[] paramArrayOfString)
  {
    HelloWorldActivity..MODULE$.main(paramArrayOfString);
  }
}
Run Code Online (Sandbox Code Playgroud)

而第二个包含:

import scala.Predef.;

public final class HelloWorldActivity$
{
  public static final  MODULE$;

  static
  {
    new ();
  }

  public void main(String[] args)
  {
    Predef..MODULE$.println("Hello, world");
  }

  private HelloWorldActivity$()
  {
    MODULE$ = this;
  }
}
Run Code Online (Sandbox Code Playgroud)

我无法理解的是以下内容:

  static
  {
    new ();
  }
Run Code Online (Sandbox Code Playgroud)

new ()内部空置的原因是什么static,以及如何static单独抛出编译/运行错误?

如果它有助于我使用http://gradle.org/docs/current/userguide/scala_plugin.html

有这个build.gradle:

apply plugin: 'scala'

repositories{
    mavenCentral()
    mavenLocal()
}

dependencies{
    compile "org.scala-lang:scala-library:2.10.1"
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*lis 7

反编译器没有在那里生成有效的Java代码.

这是javap -p -v 'HelloWorldActivity$'显示:

public static {};
  descriptor: ()V
  flags: ACC_PUBLIC, ACC_STATIC
  Code:
  stack=1, locals=0, args_size=0
     0: new           #2                  // class HelloWorldActivity$
     3: invokespecial #12                 // Method "<init>":()V
     6: return
Run Code Online (Sandbox Code Playgroud)

那只是创建一个新的类实例.因此,反编译器应该已经为静态初始化器显示了此代码:

static {
   new HelloWorldActivity$();
}
Run Code Online (Sandbox Code Playgroud)

首次加载类时,静态初始化程序执行一次.这通常会在HelloWorldActivity首次执行main方法时发生,因为这是使用的代码所在的HelloWorldActivity$位置.

请注意,静态初始化程序不会将引用存储到新创建的实例中.相反,构造函数将引用this(即对单例实例的引用)存储到MODULE$字段中.

private HelloWorldActivity$();
  descriptor: ()V
  flags: ACC_PRIVATE
  Code:
  stack=1, locals=1, args_size=1
     0: aload_0
     1: invokespecial #29                 // Method java/lang/Object."<init>":()V
     4: aload_0
     5: putstatic     #31                 // Field MODULE$:LHelloWorldActivity$;
     8: return
Run Code Online (Sandbox Code Playgroud)

或者,正如您的反编译器正确显示:

private HelloWorldActivity$() {
    MODULE$ = this;
}
Run Code Online (Sandbox Code Playgroud)

编辑:关于static {…}定义静态初始化程序的语法,请参阅Java语言规范§8.7静态初始化程序以获取参考.通过{…}在类中编写块,也可以编写实例初始化器.在创建类的每个实例时执行实例初始化器,其方式与执行字段初始化的方式非常相似.