선택적인 용도


271

6 개월 이상 동안 Java 8을 사용하고있는 새로운 API 변경에 매우 만족합니다. 내가 아직도 확신하지 못하는 영역은 언제 사용해야하는지 Optional입니다. 나는 어디에서나 사용할 수있는 곳 어디에서나 사용하려고하는 것 같습니다 null.

사용할 수있는 상황이 많이있는 것 같으며 이점 (가독성 / null 안전성)을 추가하거나 추가 오버 헤드를 유발하는지 확실하지 않습니다.

그래서 몇 가지 예가 있으며, Optional유익한 지에 대한 커뮤니티의 생각에 관심 이 있습니다.

1 - 공공 방법의 반환 형식으로 방법은 반환 할 때 null:

public Optional<Foo> findFoo(String id);

2-param이 다음 null과 같은 경우 메소드 매개 변수로 :

public Foo doSomething(String id, Optional<Bar> barOptional);

3-Bean의 선택적 멤버로서 :

public class Book {

  private List<Pages> pages;
  private Optional<Index> index;

}

4-안으로 Collections:

일반적으로 나는 생각하지 않습니다 :

List<Optional<Foo>>

값 등 filter()을 제거 하는 데 사용할 수 있기 때문에 무엇이든 추가 null하지만 Optional컬렉션에 잘 사용 됩니까?

내가 놓친 사건이 있습니까?


2
내가 유용하다고 생각하는 한 가지 사례는 예를 들어 대체 맵이있는 경우입니다. 예를 들어 Map<Character, String>. 대체가 없으면 다음을 사용할 수 있습니다 Optional.ofNullable(map.get(c)).orElse(String.valueOf(c)).. 또한 Optional은 Guava에서 도난 당했으며 훨씬 더 좋은 구문을 가지고 있습니다.Optional.fromNullable(map.get(c)).or(String.valueOf(c));
fge

3
또한 컬렉션에는 null 값을 허용하지 않는 컬렉션이 있습니다! 옵션은 여기에 청구서에 맞습니다. 그리고 당신은 .filter(Optional::absent)"널값"을
내릴

2
@fge 모든 공정성에서, Optional 이라는 개념 은 실제로 FP에서 비롯된 것이라고 생각합니다 .
VH-NZZ

2
@fge는 더 잘 표현되지 getOrDefault()않습니까?
Jim Garrison

답변:


206

요점은 Optional반환 값이 없음을 나타내는 값을 반환하는 함수를위한 수단을 제공하는 것입니다. 이 토론을 참조하십시오 . 이를 통해 호출자는 일련의 유창한 메소드 호출을 계속할 수 있습니다.

이것은 OP 질문에서 유스 케이스 1 과 가장 일치합니다 . 비록 값의 부재는 보다 더 정확한 배합이다 널 (null) 과 같은 이후 IntStream.findFirst는 null을 반환하지 않을 수는.

유스 케이스 # 2의 경우 , 선택적 인수를 메소드에 전달하면 이것이 작동하도록 만들 수 있지만 다소 어색합니다. 문자열 다음에 선택적 두 번째 문자열을 취하는 메소드가 있다고 가정하십시오. Optional두 번째 인수로 a를 허용하면 다음 과 같은 코드가 생성됩니다.

foo("bar", Optional.of("baz"));
foo("bar", Optional.empty());

null을 수락하는 것이 더 좋습니다.

foo("bar", "baz");
foo("bar", null);

아마도 가장 좋은 것은 단일 문자열 인수를 허용하고 두 번째에 대한 기본값을 제공하는 오버로드 된 메소드를 갖는 것입니다.

foo("bar", "baz");
foo("bar");

이것에는 한계가 있지만 위의 것보다 훨씬 좋습니다.

사용 예 # 3# 4 를 갖는 Optional데이터 구조 클래스 필드에 또는은 API의 오용 여겨진다. 첫째, Optional상단에 명시된 기본 설계 목표에 위배 됩니다. 둘째, 가치를 더하지 않습니다.

Optional대체 값을 제공하거나, 대체 값을 제공하기위한 함수를 호출하거나, 예외를 발생시키는 방법에는 값이없는 것을 처리하는 세 가지 방법이 있습니다 . 필드에 저장하는 경우 초기화 또는 할당 시간에이 작업을 수행합니다. OP가 언급 한 것처럼 목록에 값을 추가하는 경우 단순히 값을 추가하지 않고 추가 된 값을 "평평하게"선택할 수 있습니다.

누군가가 실제로 Optional필드 또는 컬렉션에 저장하려고하는 몇 가지 고안된 사례를 생각해 낼 수 있다고 확신 하지만 일반적 으로이 작업을 피하는 것이 가장 좋습니다.


46
# 3에 동의하지 않습니다. Optional가치의 유무에 따라 일을 수행하거나 수행하지 않을 때 필드로 사용하는 것이 유용 할 수 있습니다 .
glglgl

15
if(foo == null)필드를로 저장하는 것보다 내부 작업이 더 나은 이유를 모르겠습니다 optional. 그리고 왜 getOptionalFoo()내부적 으로 명시 적으로 호출 하는 것이 필드를 단순히로 저장하는 것보다 낫다는 것을 알지 못합니다 Optional. 또한 하나의 필드가 될 수 있고 하나의 필드가 될 수 없다면 null, 필드 null를 만들어서 컴파일러에게 Optional알리지 마십시오 Optional.
mogronalol

27
@StuartMarks, 이것은 모든 Optional<>전문가 로부터 들었을 때 나를 방해하는 것 중 하나입니다 . " Optional<>현장에 보관하지 마십시오 ". 나는이 권고의 요점을 진정으로 이해하려고 노력하고있다. 노드가 부모를 가질 수있는 DOM 트리를 고려하십시오. 유스 케이스 내에 Node.getParent()돌아 오는 것 같습니다 Optional<Node>. null매번 a를 저장하고 매번 결과를 래핑해야합니까? 왜? 코드를보기 흉하게 보이게하는 것 외에이 비효율적 인 점이 무엇입니까?
Garret Wilson

7
@GarretWilson 반면에, 당신이 있다고 가정합니다 Optional<Node> getParent() { return Optional.ofNullable(parent); }. 이것은 보이는 그것이 할당하기 때문에 비싼 Optional마다! 그러나 호출자가 즉시 포장을 풀면 객체의 수명이 매우 짧아 eden 공간에서 절대로 승진하지 않습니다. JIT의 이스케이프 분석에 의해 제거 될 수도 있습니다. 결론은 항상 "의존적"이지만 Optional필드에서 사용하면 잠재적으로 메모리 사용이 부풀려지고 데이터 구조 통과 속도가 느려집니다. 마지막으로 코드가 복잡해 보이지만 맛의 문제입니다.
스튜어트 마크

6
@GarretWilson 블로그를 작성 했습니까? 나는 그것에 관심이있을 것이다 :)
akhil_mittal

78

나는 게임에 늦었지만 가치가있는 것을 위해 2 센트를 추가하고 싶습니다. Stuart Marks의 답변으로 잘 요약 된 의 디자인 목표에Optional 반대 하지만 여전히 타당성을 확신합니다.

어디에서나 옵션 사용

일반적으로

사용에 대해Optional 전체 블로그 게시물을 작성 했지만 기본적으로 다음과 같습니다.

  • 가능한 한 선택을 피하기 위해 수업을 디자인하십시오
  • 나머지 모든 경우에 기본값은 Optional대신 사용하는 것이 좋습니다null
  • 다음에 대한 예외를 만들 수 있습니다.
    • 지역 변수
    • 개인 메소드에 값과 인수를 리턴
    • 성능이 중요한 코드 블록 (예상치 않고 프로파일 러 사용)

처음 두 예외는에서 래핑 및 래핑 해제 참조의인지 된 오버 헤드를 줄일 수 있습니다 Optional. 이들은 null이 법적으로 한 인스턴스에서 다른 인스턴스로 경계를 전달할 수 없도록 선택됩니다.

이것은 거의 Optionals만큼 나쁜 컬렉션에서 s를 거의 허용하지 않습니다 null. 하지 마십시오. ;)

당신의 질문에 대하여

  1. 예.
  2. 과부하가 옵션이 아닌 경우 가능합니다.
  3. 다른 접근 방식 (하위 클래스 링, 꾸미기 등)이 옵션이 없다면 그렇습니다.
  4. 안돼!

장점

이렇게하면 null코드 기반에서 s 의 존재가 줄어 듭니다 . 그러나 그것은 요점조차 아닙니다. 다른 중요한 장점이 있습니다.

의도를 명확하게한다

사용 Optional하면 변수가 선택 사항임을 명확하게 나타냅니다. 코드를 읽거나 API를 사용하는 소비자라면 아무 것도 없을 수 있으며 값에 액세스하기 전에 확인이 필요하다는 사실을 염두에 두어야합니다.

불확실성을 제거

없이 Optionala의 의미를 null발생 불분명하다. 상태를 합법적으로 표현 Map.get하거나 (참조 ) 초기화 누락 또는 실패와 같은 구현 오류 일 수 있습니다.

을 지속적으로 사용함에 따라 이것은 극적으로 변 Optional합니다. 여기서 이미 발생은 null버그가 있음을 나타냅니다. (값을 잃어 Optional버릴 수 있기 때문에를 사용했을 것입니다.) 이것은 이것의 의미에 대한 질문 null이 이미 답변 되었기 때문에 널 포인터 예외 디버깅을 훨씬 쉽게 만듭니다 .

더 많은 Null 검사

이제는 null더 이상 아무것도 할 수 없으므로 모든 곳에서 시행 할 수 있습니다. 주석, 어설 션 또는 일반 검사를 사용하더라도이 인수 또는 반환 유형이 null 일 수 있는지 여부를 생각할 필요가 없습니다. 할 수 없습니다!

단점

물론, 총알은 없습니다 ...

공연

추가 인스턴스에 값 (특히 프리미티브)을 래핑하면 성능이 저하 될 수 있습니다. 꽉 조이는 루프에서는 눈에 띄거나 더 나빠질 수 있습니다.

컴파일러는 수명이 짧은 수명 동안 추가 참조를 우회 할 수 있습니다 Optional. Java 10에서 값 유형 은 추가로 패널티를 줄이거 나 제거 할 수 있습니다.

직렬화

Optional직렬화 할 수 없지만 해결 방법 이 지나치게 복잡하지 않습니다.

불변

Java에서 제네릭 형식의 차이로 인해 실제 값 형식이 제네릭 형식 인수로 푸시되면 특정 작업이 번거로워집니다. 여기에 예가 있습니다 ( "파라 메트릭 다형성"참조) .


또 다른 단점 (또는 제한 사항)은 선택적 (xxx) 인스턴스를 정렬 할 수 없다는 점입니다. 그러나 Oracle은 이러한 제한을 의도적으로 의도적으로 부과했습니다. 특정 상황에서만 사용해야하는 경우에 이러한 클래스를 사용할 수 있고 개발자가 옳은 일을한다고 가정하면 지혜가 회의적입니다. 한 문제를 해결하면 다른 문제가 발생할 수 있습니다. 선택적인 (xxx) 클래스를 "원치 않는"방식 (예 : 메소드 매개 변수, 콜렉션, 생성자 등)으로 사용할 때 개발자를 돕기 위해 컴파일러 경고가 있어야 하는가?
skomisa

컬렉션의 옵션 4 정보 : 옵션을 Lists 에 저장하는 것이 실제로 유용한 경우가 있습니다 . 이는 특정 요소가 특정 색인에 있어야하지만 요소가 존재하거나 존재하지 않는 경우입니다. 그것은 List<Optional<T>>유형별로 명확하게 전달됩니다 . 반면에 어떤 개체가 어떤 컬렉션에 속하는 것이 중요하다면 아무 의미가 없습니다.
Lii

3
유스 케이스 # 2는 여전히 매우 의심 스럽다고 생각합니다. Optional방법으로 전달되는 일 수있다 null. 그래서 당신은 무엇을 얻었습니까? 이제 두 가지 확인해야합니다. 참조 stackoverflow.com/a/31923042/650176
데이비드 V

2
@DavidV는 내가 준 이점의 목록을 살펴 봅니다. 모두 해당 사례에도 적용됩니다. 게다가, 당신이 모든 것을 계속한다면 Optional(이것이 논쟁으로 기꺼이 전달하려는 경우가 그렇습니다) null결코 법적인 가치가 아닙니다. 따라서 명시 적 매개 변수를 사용하여 메서드를 호출하는 null것은 실수입니다.
Nicolai

28

개인적으로 필자는 IntelliJ의 코드 검사 도구 를 사용 @NotNull하여 @Nullable컴파일 시간이 길기 때문에 사용 하고 확인 하는 것을 선호합니다 (일부 런타임 확인 가능) 코드 가독성 및 런타임 성능 측면에서 오버 헤드가 적습니다. Optional을 사용하는 것만 큼 엄격하지는 않지만 이러한 엄격한 부족은 적절한 단위 테스트를 통해 뒷받침되어야합니다.

public @Nullable Foo findFoo(@NotNull String id);

public @NotNull Foo doSomething(@NotNull String id, @Nullable Bar barOptional);

public class Book {

  private List<Pages> pages;
  private @Nullable Index index;

}

List<@Nullable Foo> list = ..

이것은 Java 5에서 작동하며 값을 줄 바꿈하거나 줄 바꿈 할 필요가 없습니다. (또는 랩퍼 오브젝트 작성)


7
음, IDEA 주석입니까? @Nonnull개인적으로 JSR 305를 선호합니다
-FindBugs

@fge 이와 관련하여 표준이 부족하지만 도구는 일반적으로 구성 할 수 있다고 생각합니다.@Nonnull @NotNull etc
Peter Lawrey

4
응 그것은 사실이야; IDEA (13.x)는 세 가지 선택을 제공합니다 ... Meh, 저는 항상 JSR 305 anywa를 사용합니다
fge

3
나는 이것이 오래되었다는 것을 알고 있지만 주석 및 도구에 대한 토론은 stackoverflow.com/questions/35892063 / ...에 대한 링크가 필요합니다. btw는 특히 Java 8의 경우를 다루고 있습니다.
Stephan Herrmann

25

구아바 옵션과 위키 페이지에 잘 나와 있다고 생각합니다.

널 (null)에 이름을 부여함으로써 가독성이 향상되는 것 외에도, Optional의 가장 큰 장점은 바보 방지입니다. 선택 사항을 적극적으로 풀고 해당 사례를 해결해야하기 때문에 프로그램을 전혀 컴파일하지 않으려면 부재 사례에 대해 적극적으로 생각해야합니다. 널 (Null)은 단순히 물건을 잊어 버릴 수있게 해주 며 FindBugs가 도움이되지만 문제를 거의 해결하지 못한다고 생각합니다.

이것은 "존재할 수도 있고 없을 수도있는"값을 반환 할 때 특히 관련이 있습니다. other.method (a, b)가 other.method를 구현할 때 a가 null 일 수 있다는 것을 잊어 버릴 것보다 other.method (a, b)가 null 값을 반환 할 수 있다는 것을 잊어 버릴 가능성이 훨씬 높습니다. Optional을 반환하면 호출자가 코드를 컴파일하기 위해 객체 자체를 언랩해야하므로이 경우를 잊을 수 없습니다. -(출처 : Guava Wiki-null 사용 및 회피-요점은 무엇입니까? )

Optional약간의 오버 헤드가 추가되지만 객체의 부재를 명시 하고 프로그래머가 상황을 처리하도록 강요하는 것이 확실한 이점이라고 생각 합니다. 누군가가 사랑하는 != null수표를 잊어 버리는 것을 방지합니다 .

2 의 예를 들어 작성하면 훨씬 더 명확한 코드라고 생각합니다.

if(soundcard.isPresent()){
  System.out.println(soundcard.get());
}

...보다

if(soundcard != null){
  System.out.println(soundcard);
}

Optional에게는 사운드 카드가 없다는 사실을 더 잘 포착합니다.

당신의 요점에 대한 나의 2 ¢ :

  1. public Optional<Foo> findFoo(String id);-확실하지 않습니다. 어쩌면 나는 반환 Result<Foo>될 수있는 빈을 하거나를 포함 Foo. 비슷한 개념이지만 실제로는 아닙니다 Optional.
  2. public Foo doSomething(String id, Optional<Bar> barOptional);-Peter Lawrey의 답변 에서와 같이 @Nullable 및 findbugs check를 선호합니다 . 이 토론 도 참조하십시오 .
  3. 귀하의 도서 예-선택 사항을 내부적으로 사용할지 확실하지 않습니다. 복잡성에 따라 달라질 수 있습니다. 책의 "API"의 경우 책을 사용 Optional<Index> getIndex()하여 책에 색인이 없을 수 있음을 명시 적으로 나타냅니다.
  4. 컬렉션에서 사용하지 않고 컬렉션에서 null 값을 허용하지 않습니다.

일반적으로 nulls의 통과를 최소화하려고합니다 . (한 번 태워 ...) 나는 적절한 추상화를 찾아서 동료 프로그래머에게 특정 반환 값이 실제로 나타내는 것을 나타낼 가치가 있다고 생각합니다.


15
당신은 쓸 것 soundcard.ifPresent(System.out::println)입니다. 호출 isPresent은 의미 적으로 확인하는 것과 같습니다 null.
더 나은 올리버

나에게 문제는 선택적 유형의 항목이 여전히 null 일 수 있다는 것입니다. 실제로 완전히 안전하려면 다음과 같은 작업을 수행해야합니다 if(soundcard != null && soundcard.isPresent()). Optional을 반환하고 null을 반환하는 API를 만드는 것은 아무도하지 않기를 바랍니다.
Simon Baumgardt-Wellander

"옵션을 적극적으로 풀고 해당 사례를 해결해야하기 때문에 프로그램을 전혀 컴파일하지 않으려면 부재 사례에 대해 적극적으로 생각해야합니다." Java에서 많은 일을하지는 않지만 어떻게 이것을 강제 해야하는지 잘 모르겠습니다. ! isPresent 사례를 간단하게 컴파일하고 압축을 풀도록 Java에서 수행하는 작업에 대해 설명해 주시겠습니까?
호감

15

에서 오라클 튜토리얼 :

Optional의 목적은 코드베이스의 모든 단일 null 참조를 대체하는 것이 아니라 메소드의 서명을 읽음으로써 사용자가 선택적 값을 기대할 수 있는지를 알려주는 더 나은 API를 디자인하는 데 도움이되는 것입니다. 또한 Optional은 값의 부재를 처리하기 위해 Optional을 능동적으로 래핑 해제하도록합니다. 결과적으로 의도하지 않은 널 포인터 예외로부터 코드를 보호합니다.


3
메소드의 리턴 부분만을위한 API입니다. 유형 삭제 때문에 선택 사항을 매개 변수로 사용해서는 안됩니까? 때로는 nullable 매개 변수에서 변환되거나 null 생성자 매개 변수에서 필드 초기화로 메서드에서 내부적으로 Optional을 사용합니다. 이것이 null로 남겨 두는 것보다 더 유용한 지 알아 내려고 노력하고 있습니다.
ycomp

@ycomp 질문 이나 질문 에서 그러한 사례에 대한 많은 정보를 찾을 수 있습니다 . 이러한 질문에 대한 답변은 요청 된 것보다 훨씬 많은 것을 말하고 다른 사례를 다룹니다. 더 많은 정보를 원한다면 더 많은 정보를 찾아 보거나 직접 질문하십시오. ; )
ctomek

8

1-메소드가 널을 리턴 할 수있는 공용 메소드 리턴 유형

여기입니다 좋은 기사 쇼 유스 케이스 # 1의 유용성 그게. 이 코드가

...
if (user != null) {
    Address address = user.getAddress();
    if (address != null) {
        Country country = address.getCountry();
        if (country != null) {
            String isocode = country.getIsocode();
            isocode = isocode.toUpperCase();
        }
    }
}
...

이것으로 변환됩니다

String result = Optional.ofNullable(user)
  .flatMap(User::getAddress)
  .flatMap(Address::getCountry)
  .map(Country::getIsocode)
  .orElse("default");

선택적을 각 getter 메소드 의 리턴 값으로 사용 합니다.


2

다음은 흥미로운 사용법입니다.

내 프로젝트 중 하나를 심하게 테스트하려고하므로 어설 션을 작성합니다. 내가 확인해야 할 사항과 내가 확인하지 않은 사항 만 있습니다.

따라서 다음과 같이 주장하는 것을 빌드하고 주장을 사용하여 검증합니다.

public final class NodeDescriptor<V>
{
    private final Optional<String> label;
    private final List<NodeDescriptor<V>> children;

    private NodeDescriptor(final Builder<V> builder)
    {
        label = Optional.fromNullable(builder.label);
        final ImmutableList.Builder<NodeDescriptor<V>> listBuilder
            = ImmutableList.builder();
        for (final Builder<V> element: builder.children)
            listBuilder.add(element.build());
        children = listBuilder.build();
    }

    public static <E> Builder<E> newBuilder()
    {
        return new Builder<E>();
    }

    public void verify(@Nonnull final Node<V> node)
    {
        final NodeAssert<V> nodeAssert = new NodeAssert<V>(node);
        nodeAssert.hasLabel(label);
    }

    public static final class Builder<V>
    {
        private String label;
        private final List<Builder<V>> children = Lists.newArrayList();

        private Builder()
        {
        }

        public Builder<V> withLabel(@Nonnull final String label)
        {
            this.label = Preconditions.checkNotNull(label);
            return this;
        }

        public Builder<V> withChildNode(@Nonnull final Builder<V> child)
        {
            Preconditions.checkNotNull(child);
            children.add(child);
            return this;
        }

        public NodeDescriptor<V> build()
        {
            return new NodeDescriptor<V>(this);
        }
    }
}

NodeAssert 클래스에서 다음을 수행합니다.

public final class NodeAssert<V>
    extends AbstractAssert<NodeAssert<V>, Node<V>>
{
    NodeAssert(final Node<V> actual)
    {
        super(Preconditions.checkNotNull(actual), NodeAssert.class);
    }

    private NodeAssert<V> hasLabel(final String label)
    {
        final String thisLabel = actual.getLabel();
        assertThat(thisLabel).overridingErrorMessage(
            "node's label is null! I didn't expect it to be"
        ).isNotNull();
        assertThat(thisLabel).overridingErrorMessage(
            "node's label is not what was expected!\n"
            + "Expected: '%s'\nActual  : '%s'\n", label, thisLabel
        ).isEqualTo(label);
        return this;
    }

    NodeAssert<V> hasLabel(@Nonnull final Optional<String> label)
    {
        return label.isPresent() ? hasLabel(label.get()) : this;
    }
}

즉, 레이블을 확인하려는 경우 어설 션이 실제로 트리거됩니다.


2

Optionalclass를 사용하면 사용을 피하고 null더 나은 대안을 제공 할 수 있습니다 .

  • 이를 통해 개발자는 포착되지 않도록 존재 여부를 확인하도록 권장합니다 NullPointerException.

  • 누락 될 수있는 값을 예상 할 수있는 위치를 볼 수 있기 때문에 API가 더 잘 문서화됩니다.

Optional객체에 대한 추가 작업을위한 편리한 API를 제공합니다 isPresent(). get(); orElse(); orElseGet(); orElseThrow(); map(); filter(); flatmap().

또한 많은 프레임 워크가이 데이터 유형을 적극적으로 사용하여 API에서 반환합니다.


2

자바에서는 함수형 프로그래밍에 중독되지 않는 한 사용하지 마십시오.

그들은 메소드 인수로 자리를 차지하지 않습니다 (언젠가 누군가가 빈 선택 사항이 아닌 null 옵션을 전달할 것이라고 약속합니다).

그들은 반환 값에 대해서는 의미가 있지만 행동 클래스를 확장하기 위해 클라이언트 클래스를 초대합니다.

FP와 체인은 java와 같은 명령형 언어에서 거의 자리를 차지하지 않습니다. 읽기뿐 아니라 디버깅하기가 매우 어렵 기 때문입니다. 줄을 밟으면 프로그램의 상태 나 의도를 알 수 없습니다. 단계 필터에도 불구하고 종종 자신과 많은 스택 프레임이 아닌 코드로 깊이 파악해야하며 추가 한 코드 / 람다에서 중지 할 수 있도록 많은 중단 점을 추가해야합니다. 단순히 if / else / call 사소한 라인을 걷는 대신.

함수형 프로그래밍을 원한다면 java 이외의 것을 선택하고 디버깅 도구가 있기를 바랍니다.


1

선택 사항이 잠재적으로 null 값을 반환하는 메서드를 대체하는 것으로 생각하지 않습니다.

기본 아이디어는 다음과 같습니다. 값이 없다고해서 미래에 사용할 수있는 것은 아닙니다. findById (-1)와 findById (67)의 차이점입니다.

발신자에 대한 옵션의 주요 정보는 주어진 값을 신뢰할 수 없지만 언젠가는 사용할 수 있다는 것입니다. 어쩌면 다시 사라지고 나중에 다시 올 수 있습니다. 온 / 오프 스위치와 같습니다. 조명을 켜거나 끄는 "옵션"이 있습니다. 그러나 전원을 켤 수있는 조명이 없으면 옵션이 없습니다.

따라서 이전에 null이 반환 될 수있는 모든 곳에서 Optionals를 소개하는 것은 너무 지저분합니다. 나는 여전히 null을 사용하지만 트리의 루트, 게으른 초기화 및 명시적인 find-methods와 같은 제한된 영역에서만 사용합니다.


0

보인다는 Optional옵션의 종류 (T)가 같은 원시적 형태 인 경우에만 유용합니다 int, long, char, 등 "진짜"클래스의 경우, 그것은 당신이 사용할 수있는 나에게 이해가되지 않습니다 null어쨌든 값입니다.

나는 그것이 여기에서 (또는 다른 유사한 언어 개념에서) 가져온 것이라고 생각합니다.

Nullable<T>

C #에서는 Nullable<T>값 형식을 래핑하기 위해 오래 전에 소개되었습니다.


2
그것은 Optional실제로 구아바의
속임수입니다

2
@ fge OK 그러나 이것이 C # (2005, MS.NET 2.0)에있을 때 Guava가 없었습니다. 그리고 ... C #이 어디서 왔는지 아는 사람.
peter.petrov

3
@fge "구아바 선택의 립 오프 (Ripoff of Guava 's Optional)"는 구아바 사람들이 토론에 참여하고 경험을 제공하며 일반적으로 호의를 보였기 때문에 재미있는 방법입니다 java.util.Optional.
스튜어트 마크

6
@fge 의심 할 바없이 Java의 API는 구아바의 영향을 크게 받았습니다. 나는 도둑질처럼 들리는 "ripoff"문제를 겪고 있습니다. 구아바 사람은 기여 자바 8로 가치있는 아이디어를 많이
스튜어트 마크

6
요점이 없습니다. null을 리턴하는 대신 선택 사항이 사용됩니다. 잠재적으로 NullPointerException을 발생시키는 것보다 안전합니다. 참조 : oracle.com/technetwork/articles/java/…
Kilizo

0

반복자 디자인 패턴의 변경 불가능한 경우와 유사한 의미를 가지고 :Optional

  • 그것은 수도 있고 (에 의해 주어진 객체를 참조하지 않을 수 있습니다 isPresent())
  • get()객체를 참조하면 참조를 사용하여 역 참조 할 수 있습니다
  • 그러나 시퀀스의 다음 위치로 진행할 수는 없습니다 ( next()방법 이 없습니다 ).

따라서 Optional이전에 Java 사용을 고려했을 수도있는 컨텍스트에서 리턴 또는 전달 을 고려하십시오 Iterator.


-1

Java SE 8에는 java.util이라는 새로운 클래스가 도입되었습니다.

널 (NULL) 값으로 빈 선택적 또는 선택적을 작성할 수 있습니다.

Optional<String> emptyOptional = Optional.empty(); 

그리고 null이 아닌 값을 갖는 Optional이 있습니다 :

String valueString = new String("TEST");
Optional<String> optinalValueString = Optional.of(valueString );

가치가 있다면 무언가를하십시오

Optional 개체가 있으므로 값의 존재 여부를 명시 적으로 처리하는 데 사용할 수있는 메서드에 액세스 할 수 있습니다. 다음과 같이 널 검사를 수행하는 것을 기억하지 않아도됩니다.

String nullString = null;
if (nullString != null) {
    System.out.println(nullString);
}

다음과 같이 ifPresent () 메소드를 사용할 수 있습니다.

Optional<String> optinalString= null;
optinalString.ifPresent(System.out::println);

package optinalTest;

import java.util.Optional;

public class OptionalTest {
    public Optional<String> getOptionalNullString() {
        return null;
//      return Optional.of("TESt");
    }

    public static void main(String[] args) {

        OptionalTest optionalTest = new OptionalTest();

        Optional<Optional<String>> optionalNullString = Optional.ofNullable(optionalTest.getOptionalNullString());

        if (optionalNullString.isPresent()) {
            System.out.println(optionalNullString.get());
        }
    }
}

이 CopyPaste에 싼 명성을 얻을 목적으로, 영업 이익의 질문에 관련이없는
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.