Ваша проблема заключается не в методе приложения, а в попытке реализовать объект Singleton Scala в Java.
Я думаю (но не уверен), что это очень сложно, возможно даже невозможно, по дизайну.
Рассмотрим очень, очень простой случай:
object Obj;
Это составляет до двух bytcode файлов виртуальной машины Java, Obj$.class
и Obj.class
. Теоретически, просто просто проверить байт-код этих двух классов и повторить то же самое на Java. Базовая структура Scala одноэлементных объектов очень, очень проста:
- Для одноточечного объекта
Obj
, A Obj.class
и Obj$.class
должны быть сгенерированы
Obj$
класса должен иметь public final static
поля типа Obj$
под названием MODULE$
, который будет инициализирован инициализацией класса, относящейся к объекту singleton. В Scala вызовы Obj.foo()
отображаются в Obj$.MODULE$.foo()
[... если у Obj был метод с именем foo()
, то есть!]
- Компилятор Java ничего не знает об этих сгенерированных классах Scala, поэтому для Java interop
Obj
класс содержит статические функции, которые просто пересылаются на вызов метода с тем же именем и сигнатурой на Obj$.MODULE$
.
Звучит сложно, но это действительно не так много. Тривиально писать пару классов Java, которые идут так далеко. Но компилятор Scala (2.10.3) по-прежнему не признает пару как составляющую одноэлементную систему Scala. Погрузившись в байт-код генерируемого синтаксисом Scala-компилятора, вы увидите, что есть детали, которые трудно выразить в юридической Java. [Подсказка: javap -c -p -s -v <fully-qualified-class-name>
]
Например, конечное статическое поле MODULE$
инициализируется косвенно статическим инициализатором. Статический инициализатор просто создает объект Obj$
без прямого его назначения. Назначение происходит внутри частного конструктора.Это незаконно в Java: пустые статические финалы обязательно должны инициализироваться в статическом инициализаторе и не могут быть назначены в коде (например, частный конструктор), который потенциально может быть вызван извне инициализатора и несколько раз. Компилятор Scala генерирует байт-код, который уважает пустую конечную семантику (поскольку частный конструктор вызывается только один раз), но превосходит способность компилятора Java проверять эти семантики. Таким образом, этот код будет отклонен, если он выражен в Java.
Кроме того, Obj
класс (версия без знака доллара терминал) включает в себя аннотацию типа ScalaSig, который выглядит довольно сложным, и было бы трудно воспроизвести вручную (в Java или Scala), по крайней мере, для тех, мы точно не знаем, как работает эта аннотация.
Я не знаю точно, что ищет компилятор Scala, прежде чем принять решение рассматривать пару классов как «значение», то есть действительный объект Single Scala Scala, но дизайнеры Scala решили не облегчать работу, несмотря на простота базовой схемы. Вероятно, они хотят сохранить способность реорганизовывать, как объекты scala singleton переводят на байт-код. Предоставление Java-программистам синтезирования одноэлементных объектов scala фактически превратит текущую схему в постоянную часть публичного API Scala.
Обратите внимание, что запись обычного, не-одиночного класса, экземпляры которого имеют метод apply (...) и поэтому могут быть названы подобными функциями, легко из Java и отлично работает. Вот Java кошка:
public class Cat {
public String apply(int i) {
return "Meow: " + i;
}
}
Вот это использование в Scala засахаренные применяются:
Welcome to Scala version 2.10.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_45).
Type in expressions to have them evaluated.
Type :help for more information.
scala> val Morris = new Cat;
Morris: Cat = [email protected]
scala> Morris(8)
res0: String = Meow: 8
Попробуйте сделать 'apply' static:' public static OutPin apply (int pinNumber) ' – senia
Есть ли причина, по которой вы не просто реализуете функцию apply в Scala? Я думаю, как минимум, вам нужно будет применить static и сделать статический импорт функции apply. – Felix
На самом деле, я раньше делал это как статический метод, это не имеет значения. –