什么是Java的Scala对象?

时间:2022-05-14 13:43:09

In Scala, we can write

在Scala中,我们可以编写

object Foo { def bar = {} }

How is this implemented by the compiler? I am able to call Foo.bar(); from Java but new Foo(); from Java gives the error cannot find symbol symbol: constructor Foo()

编译器是如何实现的?我可以给Foo.bar()打电话;来自Java但新的Foo();从Java给出错误无法找到符号符号:构造函数Foo()

  • Does the JVM support singletons natively?
  • JVM是否原生地支持单例?
  • Is it possible to have a class in Java that does not have a constructor?
  • 有可能在Java中有一个没有构造函数的类吗?

Note: here is the code output by scalac -print

注意:这里是scalac -print的代码输出。

package <empty> {
  final class Foo extends java.lang.Object with ScalaObject {
    def bar(): Unit = ();
    def this(): object Foo = {
      Foo.super.this();
      ()
    }
  }
}

3 个解决方案

#1


11  

Support for singletons is not on a language level, but the language provides enough facilities to create them without any trouble.

对单例对象的支持不是在语言层面上,但是语言提供了足够的工具来创建它们,而不会产生任何问题。

Consider the following code:

考虑下面的代码:

public class Singleton {
    private static final Singleton instance = new Singleton();

    // Private constructor prevents instantiation from other classes
    private Singleton() {}

    public static Singleton getInstance() {
        return instance;
    }
}

This is an example from Wikipedia, which explains how a singleton can be made. An instance is kept in a private field, constructor is inaccessible outside the class, the method returns this single instance.

这是Wikipedia中的一个示例,它解释了如何创建一个单例。一个实例保存在一个私有字段中,类之外的构造函数不可访问,该方法返回这个实例。

As for constructors: every class by default has a so-called default constructor which takes no arguments and simply calls the no-args constructor of the superclass. If the superclass doesn't have any accessible constructor without arguments, you will have to write an explicit constructor.

至于构造函数:默认情况下,每个类都有一个所谓的默认构造函数,它不接受参数,只调用父类的no-args构造函数。如果超类没有无参数的可访问构造函数,则必须编写显式构造函数。

So a class must have a constructor, but you don't have to write it if the superclass has a no-args constructor.

所以一个类必须有一个构造函数,但是如果超类有一个no-args构造函数,则不必编写它。

#2


21  

When compiling your code, Scala compiler produces an equivalent of the following Java code:

在编译代码时,Scala编译器生成的Java代码相当于以下的Java代码:

public final class Foo {
    private Foo() {} // Actually, Foo doesn't have constructor at all
                     // It can be represented in bytecode, 
                     // but it cannot be represented in Java language

    public static final void bar() {
        Foo$.MODULE$.bar();
    }
}

public final class Foo$ implements ScalaObject {
    public static final Foo$ MODULE$;
    static {
        new Foo$();
    }
    private Foo$() { MODULE$ = this; }
    public final void bar() {
        // actual implementation of bar()
    }
}

Here Foo$ is an actual implementation of a singleton, whereas Foo provides a static method for interaction with Java.

在这里,Foo$是单例的实际实现,而Foo提供与Java交互的静态方法。

#3


4  

Joshua Bloch recommened in the book "Effective Java" the use of an enum to implement a singleton.

Joshua Bloch在《有效Java》一书中再次提到使用enum实现单例。

See this question: What is an efficient way to implement a singleton pattern in Java?

请参见这个问题:在Java中实现单例模式的有效方法是什么?

#1


11  

Support for singletons is not on a language level, but the language provides enough facilities to create them without any trouble.

对单例对象的支持不是在语言层面上,但是语言提供了足够的工具来创建它们,而不会产生任何问题。

Consider the following code:

考虑下面的代码:

public class Singleton {
    private static final Singleton instance = new Singleton();

    // Private constructor prevents instantiation from other classes
    private Singleton() {}

    public static Singleton getInstance() {
        return instance;
    }
}

This is an example from Wikipedia, which explains how a singleton can be made. An instance is kept in a private field, constructor is inaccessible outside the class, the method returns this single instance.

这是Wikipedia中的一个示例,它解释了如何创建一个单例。一个实例保存在一个私有字段中,类之外的构造函数不可访问,该方法返回这个实例。

As for constructors: every class by default has a so-called default constructor which takes no arguments and simply calls the no-args constructor of the superclass. If the superclass doesn't have any accessible constructor without arguments, you will have to write an explicit constructor.

至于构造函数:默认情况下,每个类都有一个所谓的默认构造函数,它不接受参数,只调用父类的no-args构造函数。如果超类没有无参数的可访问构造函数,则必须编写显式构造函数。

So a class must have a constructor, but you don't have to write it if the superclass has a no-args constructor.

所以一个类必须有一个构造函数,但是如果超类有一个no-args构造函数,则不必编写它。

#2


21  

When compiling your code, Scala compiler produces an equivalent of the following Java code:

在编译代码时,Scala编译器生成的Java代码相当于以下的Java代码:

public final class Foo {
    private Foo() {} // Actually, Foo doesn't have constructor at all
                     // It can be represented in bytecode, 
                     // but it cannot be represented in Java language

    public static final void bar() {
        Foo$.MODULE$.bar();
    }
}

public final class Foo$ implements ScalaObject {
    public static final Foo$ MODULE$;
    static {
        new Foo$();
    }
    private Foo$() { MODULE$ = this; }
    public final void bar() {
        // actual implementation of bar()
    }
}

Here Foo$ is an actual implementation of a singleton, whereas Foo provides a static method for interaction with Java.

在这里,Foo$是单例的实际实现,而Foo提供与Java交互的静态方法。

#3


4  

Joshua Bloch recommened in the book "Effective Java" the use of an enum to implement a singleton.

Joshua Bloch在《有效Java》一书中再次提到使用enum实现单例。

See this question: What is an efficient way to implement a singleton pattern in Java?

请参见这个问题:在Java中实现单例模式的有效方法是什么?