"new ()" 在 "static" 中做了什么以及 "static" 如何单独不抛出 compile/run 错误?

What does "new ()" do inside "static" and how does "static" alone not throw a compile/run error?

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

object HelloWorldActivity {
    def main(args: Array[String]) {
        println("Hello, world")
    }
}

为了理解 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);
  }
}

而第二个包含:

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;
  }
}

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

  static
  {
    new ();
  }

为什么要在 static 中放置一个空的 new (),单独使用 static 如何不抛出 compile/run 错误?

如果有帮助,我正在使用 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"
}

在java class 加载文章是这样的:

1.load static variables and methods

2.load instance variables and methods.

和静态块 static {//some code} 用于在编译器加载静态变量和方法时加载或执行某些操作。 看看这个:

public class 测试 {

   public static void main(String[] args) {
       new Test();
   }

   public Test() {
      System.out.println("i am here");
   }

   static int f = 10;

   static{
      System.out.println(f);
   }
 }

首先我们应该认为结果是: 我在这里 10

但结果是 10 我在这里

因为静态变量、方法、块正在加载 first.also 有实例 blocks.like 这个:

{
    System.out.println("i am in instance block");
}

这将在实例变量、方法和块加载步骤时加载

如果我没记错的话,Java 编译器不会生成 类 的 .class 文件,这些文件在代码中的任何地方都没有实例化。由于没有静态 main 方法,也没有创建实例,我认为这是明智的。

我不知道它是如何有效的,也许它特定于 .class 个文件。

反编译器没有生成有效的 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

这只是创建 class 的一个新实例。因此,反编译器应该为静态初始化程序显示此代码:

static {
   new HelloWorldActivity$();
}

首次加载class时执行一次静态初始化程序。这通常会在首次执行 HelloWorldActivity 中的主要方法时发生,因为那是使用 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

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

private HelloWorldActivity$() {
    MODULE$ = this;
}

编辑: 关于定义静态初始化器的 static {…} 语法,请参阅 Java 语言规范 §8.7 Static Initializers 供参考。 也可以通过在 class 中写入 {…} 块来编写实例初始化程序。在创建 class 的每个实例时执行实例初始化程序,其方式与执行字段初始化的方式大致相同。