Много лет пользуюсь Scala и до сих пор не знаю, как правильно взаимодействовать с Java. :(

Если честно, я этим не каждый день занимаюсь, но иногда другого выхода нет (сегодня это Java-библиотеки Firestore).

Сегодня мой вопрос касается правильного способа создания экземпляров POJO, которые могут иметь нулевые значения. В конце концов, я всегда использую что-то вроде def toJavaLong(l: Option[Long]): java.lang.Long = if (l.isEmpty) l.get else null, но почти уверен, что есть лучший и элегантный способ.

Пожалуйста, не могли бы вы показать мне путь? Я ожидаю, что что-то вроде orNull будет работать из коробки, но это не так.

Я использую Scala 2.13, но не стесняйтесь показывать и альтернативы Scala 3.

В следующем примере я объясню ошибки, возникающие при использовании orNull и getOrElse:

Поджо:

public class ExamplePojo {
   public Long value;

   public ExamplePojo(Long value) {
      this.value = value;
   }
}

Объект Scala, создающий экземпляр Pojo:

object CreatePojo {
  def main(args: Array[String]): Unit = {
    val noneValue = Option.empty[Long]
    val oneValue = Some(1L)

    def toJavaLong(l: Option[Long]): java.lang.Long =
      if (l.isEmpty) l.get else null

    // Next line works fine.
    new ExamplePojo(toJavaLong(noneValue))

    // Next line works fine of course, but not helpful. :)
    new ExamplePojo(oneValue.get)

    // Next line throws a compilation error:
    // type arguments [Long] do not conform to method orNull's type parameter bounds [A1 >: Long]
    new ExamplePojo(noneValue.orNull)

    // Next line throws a compilation error:
    // type mismatch;
    //  found   : Any
    //  required: Long
    new ExamplePojo(noneValue.getOrElse(null))

    // This will throw a `java.util.NoSuchElementException`
    new ExamplePojo(noneValue.get)
  }
}

Конечно, это только пример для воспроизведения случая.

3
angelcervera 31 Янв 2022 в 23:36

2 ответа

Проблема в данном случае не в null, а в том, что scala.Long не совпадает с java.lang.Long.

То, что вы можете сделать, это следующее:

new ExamplePojo(l.map(Long.box).orNull)
1
Luis Miguel Mejía Suárez 31 Янв 2022 в 23:53

Вероятно, не так кратко, как вы ожидаете, но я склонен использовать следующее:

option.getOrElse(null).asInstanceOf[java.lang.Long]

Или напишите метод расширения asJavaOrNull, который делает то, что в настоящее время делает ваш toJavaLong, но с более удобным интерфейсом для разработчиков.

0
Gaël J 31 Янв 2022 в 23:55