Java에서 null 검사없이 값을 가져 오는 중


15

오류가 발생하기 쉽고 많은 상용구가 필요한 NullPointerExceptions을 피하기 위해 일부 데이터 계층에서 값을 가져올 때 null 검사를하는 경우가 많습니다.

객체를 가져올 때 null 검사를 건너 뛸 수있는 매우 간단한 루틴을 작성했습니다 ...

public final class NoNPE {

    public static <T> T get(NoNPEInterface<T> in) {
        try {
            return in.get();
        } catch (NullPointerException e) {
            return null;
        }
    }

    public interface NoNPEInterface<T> {
        T get();
    }
}

나는 이것을 조금 사용합니다 ...

Room room = NoNPE.get(() -> country.getTown().getHouses().get(0).getLivingRoom());

위의 결과로 모든 부모 수준을 null로 확인하지 않고도 Room 객체 또는 null을 얻을 수 있습니다.

위의 생각은 무엇입니까? 문제가있는 패턴을 만들고 있습니까? 귀하의 의견으로는 더 좋은 방법이 있습니까?


1
분명히 Java 8을 사용하고 있으므로 java.util.Optional누락 된 데이터를 나타내는 데 null 대신 사용하도록 응용 프로그램을 다시 디자인하는 것이 좋습니다 . 이것은 체인의 끝에서 실패 조건을 반환하지 않고 기본 데이터를 계속 수행하려는 경우와 설명하는 경우 모두에 유용한 유틸리티를 제공합니다.
Periata Breatta

난 당신이 본질적으로 재발견했다고 생각 Option(또는 Maybe) 모나드 :
안드레스 F.을

T 또는 null 대신 Optional을 반환 할 수 있습니다.이 방법으로 orElse () 메서드를 직접 사용할 수 있습니다. 18 개월 후 누군가를 도울 수 있습니다.
Benj

이 포스트 illegalargumentexception.blogspot.com/2015/03/… 에서 또 다른 접근 방법이 언급되어 있는데 , 그중 하나는 매우 흥미로운 구문을 가진 kludje라는 라이브러리를 사용하고 있습니다
Benj

답변:


13

귀하의 솔루션은 매우 영리합니다. 내가 보는 문제는 왜 당신이 왜 당신이 모르는 사실 null입니까? 집에 방이 없었기 때문입니까? 마을에 집이 없었기 때문에? 나라에 마을이 없었기 때문입니까? 가 있었기 때문에이 되었습니까 null위치 (1) 더 큰 주택이있는 경우에도 오류로 인해 컬렉션의 0 위치를?

NonPE클래스를 광범위하게 사용 하면 심각한 디버깅 문제가 발생합니다. null더 깊은 오류를 숨길 수있는 체인을 자동으로 얻는 것보다 정확히 체인이 어디에서 깨 졌는지 아는 것이 낫다고 생각합니다 .

또한이는 위반 데메테르의 법칙 : country.getTown().getHouses().get(0).getLivingRoom(). 종종 좋은 원칙을 위반하면 그러한 원칙을 위반하여 발생하는 문제를 해결하기 위해 정통 솔루션을 구현해야합니다.

내 권장 사항은주의해서 사용하고 열차 잔해 반 패턴 에 발생하게하는 디자인 결함을 해결하려고 시도하는 것입니다 (따라서 NonPE어디에서나 사용할 필요는 없습니다 ). 그렇지 않으면 감지하기 어려운 버그가있을 수 있습니다.


좋은 대답입니다. 예, 체인에서 널이 어디에 있는지 알 수 없습니다. 신경 쓰지 않고 null 검사를하지 않아도 많은 경우 코드가 더 읽기 쉽고 상용구 오류가 발생하기 쉽습니다. 그러나 그렇습니다. 부모 객체가 null 인 경우 다른 논리적 결정을 내려야하는 경우에는 문제가 있습니다. 기존의 메소드 또는 Optional 클래스가 더 안전한 솔루션 일 수 있습니다.
Eurig Jones

일반적으로 Option모나드를 사용할 때 체인의 어디에 값이 없는지 상관하지 않습니다. 신경 쓰면 아마도와 같은 다른 유형을 사용했을 것입니다 Either.
Andres F.

OP의 접근 방식은 C # 6 ?.?[]연산자 와 비슷합니다 . 그러한 것을 사용하고 싶을 때의 예는 계층 적 서버 측 설정입니다. var shouldDoThing = settings?.a?.b?.c ?? defaultSetting;누가 왜 그 부분이 널인지 걱정합니까? 설정을 가져올 수 없습니다. 설정의 일부를 제거하기로 결정했을 수도 있습니다. 어쨌든 서버 설정에 의존 할 수는 없으므로 기본값을 사용하는 것이 좋습니다. 실제로 설정하지 않아야 할 때가 발생하지 않는 한 실제 설정을 얻을 수없는 이유는 신경 쓰지 않을 것입니다. .
chris

이제는 기본값을 현지화하고 단순히 일반 액세스를 통해 원하는 값을 얻는 것보다 낫거나 나쁘다는 말은 아닙니다 settings.a.b.c. 다시, 이것은 하나의 고립 된 예입니다.
chris

10

아이디어는 훌륭하지만 실제로는 좋습니다. Java 8 Optional유형이 존재하므로 자세한 설명은 Java Optional type 에서 찾을 수 있습니다 . 게시 한 내용의 예는 다음과 같습니다.

Optional.ofNullable(country)
    .map(Country::getTown)
    .map(Town::Houses);

그리고 더.


1
예, Java 8과 Guava의 Optional 클래스를 알고 있었고 실제로 유용합니다. 그러나 일반적으로 코드를 읽기 어렵고 성능이 떨어지는 것처럼 객체를 가져올 수는 없습니다. 그러나 Optional 클래스가 제공하는 매우 유용한 연산자가 많다는 것이 단점입니다.
Eurig Jones

3
@EurigJones 코드의 성능이 떨어질 것이라고 생각하지 않습니다. 보는 사람의 눈에는 가독성이지만 Optional, 제안과 달리 매우 일반적인 관용구 이기 때문에 두 가지 중 더 읽기 쉬운 해결책 이라고 주장 합니다 . 당신보다 훨씬 간결합니다!
Andres F.

0

디자인이 나쁜 것처럼 들리면 nulls를 반환하지만 메서드는 의도 한 목적에 맞게 충분히 작동합니다 NullPointerException.

null당신이 할 수있을 때 s를 피하고 무언가를 나타내거나 특별한 의미가있을 때만 전달하고 무언가를 나타내거나 의미 할 때만 반환하십시오 NullPointerException. 그렇지 않으면을 던져야합니다 . 이것은 버그와 혼란을 피합니다. 이 경우 Objectnull, a는 NullPointer발생한다. 객체 null가 전달 될 수 있으면 객체 가 전달 될 때 아무 것도 잘못되지 않습니다. 그렇지 않으면 위의 방법이 작동합니다.


0

나는 당신의 고통을 느낄 수 있지만 제안 된 해결책은 나쁜 생각입니다.

  • 게터 중 하나가 다른 이유로 NPE를 던지면 무시합니다.
  • 그 내부 람다가 끔찍한 코드로 자랄 위험이 있습니다. 예를 들어, 마을에 집이 없을 때 특수 상수를 반환해야하는 새로운 요구 사항이있는 경우 게으른 프로그래머는 모든 것을 래핑하여 lamda를 확장 할 수 있습니다 NoNPE.get.
  • 이미 언급했듯이, Optional.map당신이 찾고있는 것입니다.
  • NullPointerException의 새 인스턴스를 작성하는 데 따르는 처벌은 종종 중요합니다. 특히 통화 스택이 커짐에 따라 수 마이크로 초입니다. 유틸리티가 어디에서 사용되는지 예측하기는 어렵습니다.

부수적 NoNPEInterface으로의 복제본입니다 java.util.function.Supplier.

경우에 따라 많은 프레임 워크 (예 : EL, SpEL)에있는 표현식 평가 유틸리티 사용을 고려할 수 있습니다.

evaluateProperty(country, "town.houses[0].livingRoom")

웹 페이지 템플릿에는 적합하지만 일반적으로 개발 속도가 느리고 (컴파일 시간을 확인하지 않음) 실행 속도가 느립니다.
케빈 클라인
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.