"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.class
和 HelloWorldActivity$.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 的每个实例时执行实例初始化程序,其方式与执行字段初始化的方式大致相同。
我做了一个非常简单的 Scala 程序,它只打印 Hello World
:
object HelloWorldActivity {
def main(args: Array[String]) {
println("Hello, world")
}
}
为了理解 Scala 如何转换为 Java 字节码,我反编译了生成的 jar 文件,其中有两个文件:HelloWorldActivity.class
和 HelloWorldActivity$.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 的每个实例时执行实例初始化程序,其方式与执行字段初始化的方式大致相同。