null reference
null reference
누가 만들었나?
Null References:
The Billion Dollar Mistake
일반적인 상황들
public class Person {
private Home home;
public Home getHome() { return home; };
}
public class Home {
private Furniture furniture ;
public Furniture getFurniture() { return furniture; };
}
public class Furniture {
private String name;
public String getName() { return name; };
}
평범한 클래스
public String getFurnitureName(Person person) {
return person.getHome().getFurniture().getName();
}
믿음.. 신뢰.. 신용..
public String getFurnitureName(Person person) {
if (person != null) {
Home home = person.getHome();
if (home != null) {
Furniture furniture = home.getFurniture();
if (furniture != null) {
return furniture.getName();
}
}
}
return "NoName";
}
깊은 의심(deep doubt)
public String getFurnitureName(Person person) {
if (person == null) {
return "NoName";
}
Home home = person.getHome();
if (home == null) {
return "NoName";
}
Furniture furniture = home.getFurniture();
if (furniture == null) {
return "NoName";
}
return furniture.getName();
}
빠른 return!
null의 문제점
NullPointerException (NPE)
if(domain != null) {
if(domain.getKingdom() != null) {
if(domain.getKingdom().getPhylum() != null) {
if(domain.getKingdom().getPhylum().getClass() != null) {
if(domain.getKingdom().getPhylum().getClass().getOrder() != null) {
if(domain.getKingdom().getPhylum().getClass().getOrder().getFamily() != null) {
if(domain.getKingdom().getPhylum().getClass().getOrder().getFamily().getGenus() != null) {
// safe?
}
}
}
}
}
가독성
Map<String, Object> myMap = new HashMap<>();
myMap.put("myKey", null);
(myMap.get("myKey") == myMap.get("mikey")) ????
일반적인 의미가 없음
String string = null;
Integer integer = null;
Long loong = null;
Map<String, Object> map = null;
...
일반적인 의미가 없음
String str = null;
str = str + "hello"; // NPE???
System.out.println(str);
결과를 예측하기 어려움
String str = null;
str = new StringBuilder(String.valueOf(str)).append("hello").toString();
System.out.println(str); // "nullhello"
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
결과를 예측하기 어려움
공통적인 관심사
java, c, c++, scala, swift ...
def person = Person.find { it.id == 123 }
def name = person?.name
assert name == null
Groovy
Safe navigation operator
class Person {
var residence: Residence? // nil 로 초기화
}
class Residence {
var numberOfRooms = 1 // nil이 될 수 없음. 초기화 필요
}
let john = Person()
if let roomCount = john.residence?.numberOfRooms { // Optional Chaining
print("John's residence has \(roomCount) room(s).")
} else {
print("Unable to retrieve the number of rooms.")
}
Swift
Optional Type
giveIfEvan :: Int -> Maybe Int
giveIfEvan n = if n `mod` 2 == 0
then Just n
else Nothing
Haskell
Maybe
val a:Option[Int] = Some(5)
val b:Option[Int] = None
println("a.getOrElse(0): " + a.getOrElse(0) ) // 5
println("b.getOrElse(10): " + b.getOrElse(10) ) // 10
Scala
Option[T]
그렇다면 JAVA는?
JDK 1.7 까지...
GUAVA -
Google Core Libraries for Java
Requires JDK 1.6 or higher (as of 12.0).
Integer value1 = null;
Integer value2 = new Integer(10);
// null을 허용한다.
Optional<Integer> a = Optional.fromNullable(value1);
// null을 허용하지 않는다.
Optional<Integer> b = Optional.of(value2);
Guava
Optional<T>
//Optional<Integer> a, Optional<Integer> b
// 값이 없는 경우 인수로 받은 값을 반환
Integer value1 = a.or(new Integer(0));
// 값이 없는경우 throws an IllegalStateException.
Integer value2 = b.get();
Guava
Optional<T>
Guava
Optional<T>
java.util.Optional<T>
JDK 1.8 +
Optional<T>
Apple
Optional<Apple>
Optional<Apple>
Empty
Optional<T>
public class Person {
private Optional<Home> home;
public Optional<Home> getHome() { return home; };
}
public class Home {
private Optional<Furniture> furniture ;
public Optional<Furniture> getFurniture() { return furniture; };
}
public class Furniture {
private String name;
public String getName() { return name; };
}
Optional<T>
Person person = new Person();
if (person != null) {
Home home = person.getHome();
}
// java 8
Optional<Person> person = Optional.of(new Person());
Option<Home> home = person.map(Person::getHome);
Optional<T>
if (person != null) {
Home home = person.getHome();
if (home != null) {
Furniture furniture = home.getFurniture();
if (furniture != null) {
return furniture.getName();
}
}
}
return "NoName";
// java 8
person.flatMap(Person::getHome)
.flatMap(Home::getFurniture)
.map(Furniture::getName)
.orElse("NoName");
Optional<T>
Optional<T>의 장점
-
예상하지 못한 NPE 발생을 방지 할수 있다.
-
값이 반드시 있어야 하는 것과 아닌 것을 구분할 수 있다.
-
값이 없는 상황을 일관되게 처리하도록 강제 할 수 있다.
-
불필요한 코드를 줄일 수 있다. 가독성을 높힌다.
null reference
By serivires
null reference
- 668