I have a use case where
name = Person.getFirstSister().getname()
Person.getSister().getname()
gives java.lang.NullPointerException
since Person.getSister()
is java null
What is the right way to do this in scala. I am able to achieve with below code. But looking for more scala way of doing it.
private def getFirstSisterName(person: Person): String = { val sister = person.getFirstSister() if (sister == null) "" else sister.getName() }
Edit: I changed the code in the following way
private def getFirstSisterName(person: Person): Option[String] = Option(person).flatMap(l => Option(l.getFirstSister)).map(_.getName)
Advertisement
Answer
Checking for null
is the Java way to go. Scala offers a much more streamlined set of operations to avoid doing null checks manually.
Naturally, getSister
should result in an Option[Sister]
, the argument being that not every person has a sister.
Going on the same idea, trying to mimic the real word, I would ask: but what if a person has multiple sisters? How do you distinguish between them? This implies your design is not very general because it implies every person has exactly one sister.
So the idiomatic way is to have the method return a List[Sisters]
. Then map
their names from the list. If the list is empty, Nil
, the empty list will be the result, so we won’t have any NPE:
case class Sister(name: String) case class Person(sisters: List[Sister]) { def sistersNames: String = sisters.map(_.name).mkString(" ") } val p = Person(List(Sister("Sandra"), Sister("Joanna"))) val p2 = Person(List.empty) println(p.sistersNames) // Sandra Joanna println(p2.sistersNames) // empty String
EDIT:
If you can’t change Person
or Sister
, the alternative is to make your wrapper method treat the null case. You can do this in 2 ways, either use pattern matching, or wrap the result in an Option
.
Note: Option(x)
checks if x
is null and if it is, it converts it to a None
. That is why applying fold
works.
private def getFirstSisterName(person: Person): String = person.getFirstSister match { case s: Sister => s.name case _ => s"${person.toString} does not have a sister" } private def getFirstSisterName2(person: Person): String = { val sis = Option(person.getFirstSister) sis.fold(s"${person.toString} does not have a sister")(_.name) } val p = new Person(new Sister("Sandra")) val p2 = new Person(null) println(getFirstSisterName(p)) // Sandra println(getFirstSisterName2(p)) // Sandra println(getFirstSisterName(p2)) // person827966648 does not have a sister println(getFirstSisterName2(p2)) // person827966648 does not have a sister