Что такое Java-эквивалент объекта Scala?
В Scala мы можем написать
object Foo { def bar = {} }
Как это реализовано компилятором? Я могу вызвать Foo.bar();
из Java
но new Foo();
из Java дает ошибку cannot find symbol symbol: constructor Foo()
- Поддерживает ли JVM одиночные синтаксисы?
- Возможно ли иметь класс на Java, который не имеет конструктора?
Примечание: здесь выводится код scalac -print
package <empty> {
final class Foo extends java.lang.Object with ScalaObject {
def bar(): Unit = ();
def this(): object Foo = {
Foo.super.this();
()
}
}
}
Ответы
Ответ 1
Поддержка синглтонов не на уровне языка, но язык предоставляет достаточные возможности для их создания без каких-либо проблем.
Рассмотрим следующий код:
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;
}
}
Это пример из Википедии, в котором объясняется, как можно сделать одноэлемент. Экземпляр хранится в закрытом поле, конструктор недоступен вне класса, метод возвращает этот единственный экземпляр.
Что касается конструкторов:, каждый класс по умолчанию имеет так называемый конструктор по умолчанию, который не принимает аргументов и просто вызывает конструктор no-args суперкласса. Если суперкласс не имеет никакого доступного конструктора без аргументов, вам нужно будет написать явный конструктор.
Итак, класс должен иметь конструктор, но вам не нужно его писать, если суперкласс имеет конструктор no-args.
Ответ 2
При компиляции кода компилятор Scala создает эквивалент следующего кода 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()
}
}
Здесь Foo$
является реальной реализацией одноэлементного кода, тогда как Foo
предоставляет метод static
для взаимодействия с Java.
Ответ 3
Джошуа Блох в книге "Эффективная Java" рекомендовал использовать перечисление для реализации синглета.
Смотрите этот вопрос:
Что такое эффективный способ реализации одноэлементного шаблона в Java?