Optional
Java에 추가 된 이유 는 다음과 같습니다.
return Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
.stream()
.filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
.filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses))
.filter(m -> Objects.equals(m.getReturnType(), returnType))
.findFirst()
.getOrThrow(() -> new InternalError(...));
이보다 깨끗합니다.
Method matching =
Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
.stream()
.filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
.filter(m -> Arrays.equals(m.getParameterTypes(), parameterClasses))
.filter(m -> Objects.equals(m.getReturnType(), returnType))
.getFirst();
if (matching == null)
throw new InternalError("Enclosing method not found");
return matching;
내 요점은 Optional이 함수형 프로그래밍을 지원하기 위해 작성되었으며 동시에 Java에 추가되었다는 것입니다. (이 예제는 Brian Goetz 의 블로그 에서 제공 한 것입니다 . orElse()
이 코드는 예외를 발생 시키지만이 방법을 사용하면 더 좋은 예제를 사용할 수 있습니다 .)
그러나 이제 사람들은 매우 다른 이유로 Optional을 사용하고 있습니다. 그들은 언어 디자인의 결함을 해결하기 위해 그것을 사용하고 있습니다. 결함은 다음과 같습니다. 어떤 API 매개 변수 및 리턴 값이 널 (null)이 될 수 있는지 지정할 방법이 없습니다. javadocs에서 언급 될 수 있지만 대부분의 개발자는 코드에 대해 javadoc을 작성하지 않으며 작성하는 javadoc을 확인하는 사람은 많지 않습니다. 따라서 호출 스택에서 9-10 회 반복해서 이미 유효성이 검사 되었기 때문에 null 일 수없는 경우에도 사용하기 전에 항상 null 값을 확인하는 많은 코드가 생성됩니다.
새로운 Optional 클래스를 본 많은 사람들이 그 목적이 API에 명확성을 추가하는 것이라고 가정했기 때문에이 결함을 해결하기위한 갈증이 있다고 생각합니다. 사람들이 "게터가 옵션을 돌려줘야합니까?"와 같은 질문을하는 이유는 무엇입니까? 아닙니다. getter가 함수형 프로그래밍에 사용될 것으로 예상하지 않는 한 아마 그렇게해서는 안됩니다. 실제로 Java API에서 Optional이 사용되는 위치를 살펴보면 주로 기능 프로그래밍의 핵심 인 Stream 클래스에 있습니다. (매우 철저히 확인하지는 않았지만 Stream 클래스가 유일하게 사용되는 장소 일 수 있습니다 .)
약간의 기능적 코드에서 getter를 사용하려는 경우 표준 getter와 Optional을 리턴하는 두 번째 getter를 갖는 것이 좋습니다.
아, 그리고 클래스를 직렬화 할 수 있어야한다면 Optional을 절대 사용해서는 안됩니다.
옵션은 a) 매우 장황하고 b) 처음에는 해당 문제를 해결하려는 의도가 없었기 때문에 API 결함에 대한 매우 나쁜 해결책입니다.
API 결함에 대한 훨씬 더 나은 솔루션은 Nullness Checker 입니다. @Nullable로 주석을 달아 어떤 매개 변수와 반환 값이 null이 될 수 있는지 지정할 수있는 주석 처리기입니다. 이런 식으로 컴파일러는 코드를 스캔하고 실제로 null 일 수있는 값이 null이 허용되지 않는 값으로 전달되는지 알아낼 수 있습니다. 기본적으로 주석이 달린 경우를 제외하고는 null이 될 수 없다고 가정합니다. 이렇게하면 null 값에 대해 걱정할 필요가 없습니다. 널값을 매개 변수에 전달하면 컴파일러 오류가 발생합니다. 널이 될 수없는 널에 대해 오브젝트를 테스트하면 컴파일러 경고가 생성됩니다. 그 결과 NullPointerException이 런타임 오류에서 컴파일 타임 오류로 변경됩니다.
이것은 모든 것을 바꿉니다.
게터에 대해서는 옵션을 사용하지 마십시오. 그리고 멤버가 null이 될 수 없도록 클래스를 디자인하십시오. 그리고 Nullness Checker를 프로젝트에 추가하고 필요한 경우 getter 및 setter 매개 변수를 @Nullable 선언하십시오. 나는 새로운 프로젝트로만 이것을했습니다. null에 대한 많은 불필요한 테스트로 작성된 기존 프로젝트에서 많은 경고를 생성하므로 개조하기가 어려울 수 있습니다. 그러나 그것은 또한 많은 버그를 잡을 것입니다. 나는 그것을 좋아한다. 내 코드는 훨씬 깨끗하고 안정적입니다.
(이 문제를 해결하는 새로운 언어도 있습니다. Java 바이트 코드로 컴파일되는 Kotlin을 사용하면 객체를 선언 할 때 객체가 null인지 여부를 지정할 수 있습니다. 더 깔끔한 방법입니다.)
원본 게시물의 부록 (버전 2)
많은 생각을 한 후에 한 가지 조건에서 Optional을 반환하는 것이 허용된다는 결론에 마지 못해왔다. 사람들이 null을 반환 할 수없는 getter에서 Optional을 정기적으로 반환하는 많은 코드를 보았습니다. 나는 이것이 코드에 복잡성을 추가하여 버그를 일으킬 가능성이 매우 나쁜 코딩 관행이라고 생각합니다. 그러나 반환 된 값이 실제로 null 일 경우 계속해서 Optional 내부에 래핑하십시오.
함수형 프로그래밍을 위해 설계되었으며 함수 참조가 필요한 메소드는 두 가지 형식으로 작성되며 그 중 하나는 선택 사항을 사용합니다. 예를 들어, Optional.map()
및 Optional.flatMap()
모두 걸릴 함수 참조. 첫 번째는 일반적인 getter에 대한 참조를 가져오고 두 번째는 Optional을 반환하는 것을 가져옵니다. 따라서 값을 null로 설정할 수없는 Optional을 반환하여 호의를 베풀지 않습니다.
모든 것을 말했지만, 여전히 Nullness Checker 가 사용하는 접근 방식 이 NullPointerExceptions을 런타임 버그에서 컴파일 타임 오류로 전환하기 때문에 null을 처리하는 가장 좋은 방법이라고 생각합니다.