Constructor.newInstance заменяет объект Scala - PullRequest
6 голосов
/ 16 апреля 2019

Я отлаживал проблему десериализации с Джексоном, где казалось, что экземпляры Scala object заменены.Мне удалось детализировать проблему до этого кода:

object WaitWhat extends App {

  object XX

  val x1 = XX

  // Notice: no assignment!
  XX.getClass.getConstructor().newInstance()

  val x2 = XX

  println(x1)
  println(x2)
}

Вывод:

WaitWhat$XX$@5315b42e
WaitWhat$XX$@2ef9b8bc

(Конечно, фактические хэш-коды меняются при каждом запуске.)

* 1009Отладчик IntelliJ также указывает, что x1 и x2 действительно являются разными экземплярами, несмотря на тот факт, что результат newInstance полностью игнорируется.

Я бы ожидал неоперацию или исключениекакой-тоКак это возможно, что фактический экземпляр объекта получает , замененный этим вызовом?

1 Ответ

6 голосов
/ 16 апреля 2019

Объекты в Scala имеют закрытый конструктор, который нельзя вызывать с помощью new (поскольку он приватный), но все же можно вызывать с помощью отражения.

Под капотом объект доступен через статическое поле MODULE$. Это поле является экземпляром синглтона, созданным внутри, путем вызова частного конструктора.

Пока вы обращаетесь к объекту в Scala или в коде Java с помощью MODULE$, все будет в порядке. Однако вы не можете быть уверены, что какая-то библиотека не создаст дополнительный экземпляр вашего объекта с помощью частного конструктора, использующего отражение. В этом случае всякий раз, когда будет вызываться закрытый конструктор, будет создан новый экземпляр объекта и переназначен на MODULE$.

Это может произойти, особенно если вы используете библиотеки Java, которые не знают о существовании объектов Scala.

Пожалуйста, проверьте эту статью для более подробной информации.

В любом случае, я бы просто создал собственный десериализатор для Джексона (аналогично решению, описанному в статье).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...