인수에 Java 8의 Optional을 사용하지 않아야하는 이유


392

많은 웹 사이트에서 읽었습니다. Optional은 반환 유형으로 만 사용해야하며 메서드 인수에는 사용하지 않아야합니다. 나는 논리적 인 이유를 찾기 위해 고심하고 있습니다. 예를 들어 2 개의 선택적 매개 변수가있는 논리가 있습니다. 따라서 다음과 같이 메서드 서명을 작성하는 것이 좋습니다 (솔루션 1).

public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2 {
    // my logic
}

많은 웹 페이지는 Optional을 메소드 인수로 사용해서는 안된다고 지정합니다. 이를 염두에두고 다음 메소드 서명을 사용하고 명확한 Javadoc 주석을 추가하여 인수가 null 일 수 있음을 지정하면 향후 관리자가 Javadoc을 읽고 인수를 사용하기 전에 항상 null 검사를 수행하기를 희망합니다 (솔루션 2) :

public int calculateSomething(String p1, BigDecimal p2) {
    // my logic
}

또는 더 나은 인터페이스를 제공하고 p1과 p2가 선택 사항이되도록 분명하게하기 위해 메서드를 4 개의 공용 메서드로 대체 할 수 있습니다 (솔루션 3).

public int calculateSomething() {
    calculateSomething(null, null);
}

public int calculateSomething(String p1) {
    calculateSomething(p1, null);
}

public int calculateSomething(BigDecimal p2) {
    calculateSomething(null, p2);
}

public int calculateSomething(String p1, BigDecimal p2) {
    // my logic
}

이제 각 접근 방식 마다이 논리를 호출하는 클래스 코드를 작성하려고합니다. 먼저 Optionals 를 반환하는 다른 객체에서 두 개의 입력 매개 변수를 검색 한 다음 invoke calculateSomething합니다. 따라서 솔루션 1을 사용하면 호출 코드는 다음과 같습니다.

Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1, p2);

솔루션 2를 사용하는 경우 호출 코드는 다음과 같습니다.

Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1.orElse(null), p2.orElse(null));

솔루션 3을 적용하면 위의 코드를 사용하거나 다음을 사용할 수 있습니다 (그러나 훨씬 더 많은 코드).

Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result;
if (p1.isPresent()) {
    if (p2.isPresent()) {
        result = myObject.calculateSomething(p1, p2);
    } else {
        result = myObject.calculateSomething(p1);
    }
} else {
    if (p2.isPresent()) {
        result = myObject.calculateSomething(p2);
    } else {
        result = myObject.calculateSomething();
    }
}

그래서 내 질문은 : 왜 Optional메소드 인수로 s 를 사용하는 것이 나쁜 습관으로 간주 됩니까? 그것은 나에게 가장 읽기 쉬운 솔루션처럼 보이며 매개 변수가 미래 관리자에게 비어 있거나 null 일 수 있음을 가장 분명하게 만듭니다. (디자이너가 Optional반환 유형으로 만 사용하도록 의도했지만이 시나리오에서 사용하지 않는 논리적 이유는 없습니다.)


16
옵션을 사용했다면 매개 변수로 전달 된 옵션이 아닌지 확인하지 않아도됩니다 null.
biziclop

17
예, 그러나 미래에 코드를 유지 관리하는 다른 사람에게는 매개 변수가 비어 있거나 널이 될 수 있으므로 향후 널 포인터 예외를 피할 수 있습니다.
Neil Stevens

1
와. 널 인수가 메소드에 전달됩니까? 정말 Visual Basic입니다. 어떤 원칙을 위반합니까? SRP (아마도). 그것은 또한 그 이름이 나를 떠나게하는 또 다른 원칙을 어기는 것입니다.
Luminous

20
이론적으로 null 일 수있는 모든 것은 System.exit (0)을 호출 할 수있는 라이브러리의 모든 메소드와 같습니다. 당신은 tis를 확인할 수 없으며 이것에 대해 점검해서는 안됩니다. 당신이 실제로 (거의) 절대로하지 않아야 할 모든 시간을 당신이해야 할 모든 것. 모든 매개 변수를 최종적으로 만드는 것과 같습니다. 수천 개의 결승 및 널 검사로 코드를 읽을 수 없게 만드는 대신 도구를 사용하여 매개 변수 값을 변경하거나 필드를 초기화하지 못하게 할 수 있습니다.
yeoman

6
실제로 NonNull / Nullable 어노테이션 만 사용하십시오. 이것이 선택 사항이 아닌이 상황에서 찾고있는 것입니다.
Bill K

답변:


202

아, 그 코딩 스타일은 약간의 소금으로 찍어야합니다.

  1. (+) 의미 론적 분석없이 선택적인 결과를 다른 방법으로 전달; 그 방법으로 그것을 떠나는 것은 꽤 괜찮습니다.
  2. (-) 메소드 내부에서 조건부 논리를 유발하는 선택적 매개 변수를 사용하는 것은 문자 그대로 비생산적입니다.
  3. (-) 선택 사항에서 인수를 압축해야하는 것은 컴파일러에게는 적합하지 않으며 불필요한 랩핑을 수행합니다.
  4. (-) nullable 매개 변수와 비교하여 선택 사항이 더 비쌉니다.

일반적으로 : 옵션은 해제해야하는 두 가지 상태를 통합합니다. 따라서 데이터 흐름의 복잡성 때문에 입력보다 결과에 더 적합합니다.


38
실제로, Optional매개 변수 를 갖는 것은 세 가지 상태 중 하나를 나타냅니다. null선택 사항, 널 Optional이 아닌 값 isPresent() == false및 널 이 아닌 Optional값으로 실제 값 랩핑.
biziclop

16
@biziclop 예, 피할 수없는 점은 이미 비난했습니다. 그러나 의도 는 널이 아닌 표현식 만 갖는 것입니다. 선택을 피하라는 충고를 들으려면 오래 걸리지 않았다는 것 역시 선택의 여지가 있습니다. @NotNull Optional.
Joop Eggen

80
@biziclop 만약 당신이 Optional전혀 사용하지 않는다면 , 상태 1 ( null선택 사항)은 일반적으로 프로그래밍 에러를 나타내므로, 처리하지 않을 수도 있습니다 (그냥 던져 보자 NullPointerException)
user253751

50
"컴파일러에 대해 차선책", "널 (NULL) 입력 가능 매개 변수에 비해 선택 사항이 더 비싸다"-이러한 인수는 Java 언어가 아닌 C 언어에 유효 할 수 있습니다. Java 프로그래머는 "선택 사항이 널 (null) 참조보다 비용이 많이 듭니다"가 아니라 깨끗한 코드, 이식성, 테스트 가능성, 우수한 아키텍처, 모듈성 등에 중점을 두어야합니다. 그리고 미세 최적화에 집중해야한다는 것을 알게되면 Objects, Lists, Generics를 건너 뛰고 배열과 프리미티브로 전환하는 것이 좋습니다 (여기서는 불쾌감을 원하지 않습니다. 저는 의견을 공유하고 있습니다) .
Kacper86

15
"컴파일러에 대해 차선책": 조기 최적화는 모든 악의 근원입니다 ... 성능에 중요한 코드를 작성하지 않는 경우 (정확한 인터페이스를 지정하려고 할 때 종종 그렇습니다), 이것은 걱정할 필요가 없습니다.
Mohan

165

최고의 포스트 나는 주제에서 본이 쓴 다니엘 Olszewski :

필수 메소드 매개 변수가 아닌 경우 선택 사항을 고려하고 싶은 유혹이있을 수 있지만, 그러한 대안은 다른 대안과 비교하여 창백합니다. 문제를 설명하려면 다음 생성자 선언을 검사하십시오.

public SystemMessage(String title, String content, Optional<Attachment> attachment) {
    // assigning field values
}

언뜻보기에 올바른 디자인 결정으로 보일 수 있습니다. 결국 첨부 파일 매개 변수를 선택적으로 표시했습니다. 그러나 생성자를 호출하는 경우 클라이언트 코드가 약간 어색해질 수 있습니다.

SystemMessage withoutAttachment = new SystemMessage("title", "content", Optional.empty());
Attachment attachment = new Attachment();
SystemMessage withAttachment = new SystemMessage("title", "content", Optional.ofNullable(attachment));

명확성을 제공하는 대신 선택적 클래스의 팩토리 메소드는 독자를 혼란스럽게합니다. 선택적 매개 변수는 하나 뿐이지 만 2 ~ 3 개가 있다고 상상해보십시오. 밥 삼촌은 분명히 그런 코드를 자랑스럽게 생각하지 않을 것입니다.

메소드가 선택적 매개 변수를 승인 할 수있는 경우, 검증 된 접근 방식을 채택하고 메소드 오버로드를 사용하여 이러한 경우를 설계하는 것이 좋습니다. SystemMessage 클래스의 예에서 두 개의 개별 생성자를 선언하는 것이 Optional을 사용하는 것보다 우수합니다.

public SystemMessage(String title, String content) {
    this(title, content, null);
}

public SystemMessage(String title, String content, Attachment attachment) {
    // assigning field values
}

이러한 변경으로 인해 클라이언트 코드가 훨씬 간단하고 읽기 쉽습니다.

SystemMessage withoutAttachment = new SystemMessage("title", "content");
Attachment attachment = new Attachment();
SystemMessage withAttachment = new SystemMessage("title", "content", attachment);

10
하나 또는 두 개의 단락 만 관련 될 때 많은 복사 + 붙여 넣기입니다.
Garret Wilson

47
불행하게도이 설명은 발신자가 예를 들어 파싱하는 경우의 문제를 다루지 않으며 일부 정보는 선택 사항 일 수 있습니다. 메서드 오버로딩 (위에서 권장하는대로)을 호출하면 호출 코드는 "X가 있습니까? 그렇다면 오버로드 된 메서드 A를 호출합니다. Y가 있습니까? 오버로드 된 메서드 B를 호출해야합니다. X 및 Y 인 경우 현재 오버로드 된 메소드 C를 호출해야합니다. " 등등. 이에 대한 좋은 대답이있을 수 있지만 "왜"에 대한 설명에서는 다루지 않습니다.
Garret Wilson

9
또한 컬렉션과 관련하여 비어있는 컬렉션과 컬렉션이없는 경우에는 뚜렷한 차이가 있습니다. 예를 들어, 캐시입니다. 캐시 미스였습니까? 비어있는 옵션 / null. 빈 컬렉션으로 발생하는 캐시 적중이 있습니까? 전체 옵션 / 수집.
Ajax

1
@ 아약스 당신이 기사를 오해하고 있다고 생각합니다. 그것들은 Effective Java 책에서 주장하는 요점을 인용하고 있는데, 이는 메소드 반환 유형이 Collection (캐시가 반환 할 때 임의의 객체가 아닌) 일 때 null또는 대신 빈 컬렉션을 반환하는 것을 선호한다고 말합니다 Optional.
길리

4
물론 코드를 선호 해야 하지만 항상 일부 코드를 제어 할 수있는 것은 아니며, 실제로는 "값이 있고 빈 컬렉션"과 "아니오가 있습니다"를 구분할 수 있습니다. 정의 된 값 (아직) ". "매직 널 (magic null)"은 또한 권장하지 않는 방법이므로, 가장 나쁜 옵션을 선택하는 것은 개발자에게 달려 있습니다. 나는 실제 캐시 값은 수 있기 때문에, 빈 콜렉션 대신 캐시 미스를 나타내는 빈 옵션을 선호 빈 콜렉션.
Ajax

86

Optional매개 변수로 사용하지 않는 이유는 거의 없습니다 . 이것에 대한 주장은 권위의 주장에 의존합니다 (Brian Goetz-그의 주장은 우리가 null이 아닌 선택 사항을 강제 할 수 없다는 것입니다 Optional). 물론 Java의 모든 참조는 null 일 수 있으므로 프로그래머 메모리가 아닌 컴파일러가 규칙을 시행하도록 권장해야합니다 (문제가 있고 확장되지 않습니다).

기능적 프로그래밍 언어는 Optional매개 변수를 권장 합니다. 이것을 사용하는 가장 좋은 방법 중 하나는 여러 개의 선택적 매개 변수를 사용 liftM2하고 매개 변수가 비어 있지 않은 것으로 가정하고 함수를 사용하는 것입니다 ( http://www.functionaljava.org/javadoc/4.4/functionaljava/fj/ 참조) . data / Option.html # liftM2-fj.F- ). Java 8은 불행히도 선택적을 지원하는 매우 제한된 라이브러리를 구현했습니다.

Java 프로그래머로서 레거시 라이브러리와 상호 작용하기 위해 null 만 사용해야합니다.


3
대신 javax.annotation을 사용 @Nonnull하고 사용 @Nullable하는 것은 어떻습니까? 필자는 개발 한 라이브러리에서 광범위하게 사용하며 IDE (IntelliJ)에서 제공하는 지원은 매우 좋습니다.
Rogério

1
괜찮습니다.하지만이 주석을 어디에서나 사용해야하며 map, flatMap / bind, liftM2, sequence 등과 같은 메소드를 지원하는 라이브러리가 필요합니다.
Mark Perry

14
기능적 프로그래밍 언어는 선택적 매개 변수를 권장합니다. 인용이 필요했습니다. 대부분의 기능은 선택 사항이 아닙니다. 대신, 값의 존재 또는 부재를 다루는 (적절한 고차 함수 사용) 책임은 해당 함수의 호출자에게 있습니다.
jub0bs

5
이. 실제로, 어떤 대답도 충분히 설득력이 없으며, 이들 중 어떤 것도 "방법 매개 변수로 옵션을 사용하는 것이 나쁜 습관으로 간주되는 이유 @NonNull는 무엇입니까? 다른 방법으로 동일한 목적을 수행하는 경우 분석법 매개 변수에 주석을 달는 것이 완전히 괜찮은 이유 는 무엇입니까?" 저에게는 적어도 이해가되는 하나의 인수 만 있습니다 : "선택적인 방식은 명확한 반환 유형을 가진 더 나은 API를 제공하는 데 사용해야합니다. 그러나 메소드 인수의 경우 오버로드 된 함수를 사용할 수 있습니다." -아직도, 나는 이것이 충분히 강력한 주장이라고 생각하지 않습니다.
Utku Özdemir

1
null로보다 더 낫다 물론, 중,하지만 훨씬 더보다 더 낫다 것은 처음에 옵션 값이 많이 필요하지 않는 것입니다 좋은 디자인 때문에 : D
유사시

12

이 조언은 "입력에 대해서는 가능한 한 구체적이지 않고 출력에 대해서는 가능한 구체적이지 않다"는 규칙의 변형입니다.

일반적으로 널이 아닌 일반 값을 취하는 메소드가있는 경우이를 널에 맵핑 할 수 Optional있으므로 일반 버전은 입력과 관련하여 더 구체적이지 않습니다. 그러나Optional 그럼에도 불구하고 논쟁 이 필요한 여러 가지 이유가 있습니다 .

  • 함수를 반환하는 다른 API와 함께 사용하기를 원합니다. Optional
  • Optional주어진 값이 비어 있으면 함수는 비어있는 것 이외의 것을 반환해야합니다
  • 당신은 생각 Optional합니다 누구든지 당신의 API가 그것에 대해 배울해야한다 너무 굉장합니다 ;-)

10

with 패턴 Optional리턴 을 피하기위한 것 null입니다. null메소드 에 전달하는 것은 여전히 ​​가능합니다 .

이것들은 아직 공식적이지는 않지만 JSR-308 스타일 주석을 사용 null하여 함수에 값을 수락할지 여부를 나타낼 수 있습니다. 실제로이를 식별하려면 올바른 툴링이 있어야하며 실행 가능한 런타임 정책보다 더 많은 정적 검사를 제공하지만 도움이 될 것입니다.

public int calculateSomething(@NotNull final String p1, @NotNull final String p2) {}

여기서 문제는 @NotNull이 기본 사례가 아니며 명시 적으로 주석을 달아야한다는 것입니다. 따라서 보일러 플레이트 및 사람들이 게으름으로 인해하지 않을 것입니다.
dwegener

1
@dwegener 예, 그러나 Optional문제를 해결하지 않으므로 주석에 대한 제안입니다.
Makoto

2
무시하는 것이 훨씬 어렵습니다. 문서 / 소스를 읽거나 툴링이이를 포착 할 수있는 경우에만 알 수있는 주석을 무시하는 것보다 선택적입니다.
Ajax

@Nullable은 null을 유효한 값으로 "수락"한다는 의미는 아닙니다. 즉, 예외를 발생시키지 않습니다. 그것은 당신 이이 사건을 경계하고 있음을 의미하지만 여전히 예외를 던질 것입니다 (이것은 Findbugs 의미론입니다). 따라서 명확성 대신 이러한 주석으로 모호성을 도입 할 수 있습니다.
tkruse 2012 년

@ user2986984에 어떤 모호성이 있는지 잘 모르겠습니다. "null 처리하지 않음"은 사실적으로 예외가 발생했음을 의미 할 수 있습니다.
Makoto

7

이것은 나에게 약간 어리석은 것처럼 보이지만 내가 생각할 수있는 유일한 이유는 메소드 매개 변수의 객체 인수가 이미 선택적인 방법이기 때문에 null 일 수 있다는 것입니다. 따라서 누군가 기존 객체를 가져 와서 선택 사항으로 감싸도록 강요하는 것은 무의미합니다.

즉, 선택 사항을 가져 오거나 반환하는 체인 방법을 함께 묶는 것이 합리적 일입니다 (예 : 아마도 모나드).


7
값과 필드도 null을 반환 할 수 없습니까? 그래서 Optional완전히 무의미?
사무엘 에드윈 워드


4

필자는 Optional이 Monad이어야하며 Java에서는 생각할 수 없다는 것입니다.

함수형 프로그래밍에서는 "비즈니스 도메인 유형"을 기반으로 만 인수를 취하고 구성하는 순수하고 고차 함수를 처리합니다. 현실 세계 (소위 부작용이라고 함)에 피드를 제공하거나 계산해야하는 기능을 구성하려면 외부 세계를 나타내는 모나드에서 값을 자동으로 압축 해제하는 기능을 적용해야합니다 (상태, 구성, 선물, 아마도, 작가, 작가 등 ...); 이것을 리프팅이라고합니다. 이를 일종의 우려 분리라고 생각할 수 있습니다.

이 두 수준의 추상화를 혼합해도 가독성이 떨어 지므로 피하는 것이 좋습니다.


3

Optionalas 매개 변수를 전달할 때주의해야 할 또 다른 이유 는 메서드가 한 가지 작업을 수행해야한다는 것입니다. Optional매개 변수를 전달하면 둘 이상의 작업을 수행 할 수 있습니다.

public void method(Optional<MyClass> param) {
     if(param.isPresent()) {
         //do something
     } else {
         //do some other
     }
 }

나는 그것이 좋은 이유가 아니라고 생각합니다. 선택 사항이 아닌 경우 param이 null인지 확인하기 위해 동일한 논리를 적용 할 수 있습니다. 실제로, if(param.isPresent())옵션을 사용하는 가장 좋은 방법은 아닙니다. 대신 다음을 사용할 수 있습니다.param.forEach(() -> {...})
hdkrus

나는 nullable 매개 변수를 전달한다는 아이디어가 마음에 들지 않습니다. 어쨌든, 나는 당신이 그것을 사용할 수 있다고 말할 수 있습니다. 물론 당신이 그것을 사용할 수있는 예외가 있습니다, 그것은 당신에게 달려 있습니다. 모든 시나리오에 적용되는 규칙은 없습니다.
Pau

2

선택 사항을 매개 변수로 허용하면 호출자 수준에서 불필요한 줄 바꿈이 발생합니다.

예를 들면 다음과 같습니다.

public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2 {}

널이 아닌 두 개의 문자열이 있다고 가정하십시오 (예 : 다른 방법에서 반환).

String p1 = "p1"; 
String p2 = "p2";

비어 있지 않다는 것을 알더라도 선택 사항으로 랩핑해야합니다.

다른 "매핑 가능한"구조로 작성해야 할 때, 즉 더욱 악화됩니다. Eithers :

Either<Error, String> value = compute().right().map((s) -> calculateSomething(
< here you have to wrap the parameter in a Optional even if you know it's a 
  string >));

심판 :

메소드는 옵션을 매개 변수로 기 대해서는 안되며, 이는 거의 항상 발신자에서 수신자에게 제어 흐름의 누출을 나타내는 코드 냄새입니다. 옵션의 내용을 확인하는 것은 호출자의 책임입니다.

심판. https://github.com/teamdigitale/digital-citizenship-functions/pull/148#discussion_r170862749


1

필자는 일반적으로 데이터를 조작하는 함수를 작성하고 Optional사용 map하고 유사한 함수 로 들어 올리기 때문이라고 생각합니다 . 기본 Optional동작 이 추가 됩니다. 물론에서 작동하는 자체 보조 기능을 작성해야하는 경우가있을 수 있습니다 Optional.


1

나는 선택의 여지가 먼저 null인지 여부를 확인한 다음 감싸는 값을 평가해야한다고 생각합니다. 불필요한 검증이 너무 많습니다.


2
null 선택적 전달은 선택적 오류 로 "빈"값을 전달 하는 명시 적 방법을 제공하므로 프로그래밍 오류로 간주 될 수 있으므로 모든 경우에 예외가 발생하지 않도록하려면 검사 할 가치가 없습니다.
pvgoran

1

Brian Goetz가 잘 설명했듯이 옵션은 이러한 목적으로 설계되지 않았습니다 .

항상 @Nullable 을 사용하여 메서드 인수가 null 일 수 있음을 나타냅니다. 옵션을 사용한다고해서 메소드 논리를 더 깔끔하게 작성할 수있는 것은 아닙니다.


5
죄송하지만 "설계되지 않았습니다"또는 "누군가 추천하지 않습니다"라는 주장에 동의 할 수 없습니다. 우리가 구체적으로 기술해야하는 엔지니어. Optional은 API 관점에서 훨씬 더 장황하기 때문에 @Nullable을 사용하는 것은 Optional을 사용하는 것보다 훨씬 나쁩니다. Optionals를 인수로 사용하지 않는 데는 아무런 이유가 없습니다 (메소드 오버로드를 사용하지 않으려는 경우)
Kacper86

0

하나 더 접근, 당신이 할 수있는 것은

// get your optionals first
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();

// bind values to a function
Supplier<Integer> calculatedValueSupplier = () -> { // your logic here using both optional as state}

함수 (이 경우 공급자)를 작성하면이를 다른 변수로 전달하고 다음을 사용하여 호출 할 수 있습니다

calculatedValueSupplier.apply();

선택적인 값을 가지고 있는지 아닌지에 대한 아이디어는 함수의 내부 세부 사항이며 매개 변수가 아닙니다. 선택적 매개 변수로 생각할 때 함수를 생각하는 것은 실제로 내가 찾은 매우 유용한 기술입니다.

실제로 해야하는지 여부에 대한 귀하의 질문에 대해서는 귀하의 선호도를 기반으로하지만 다른 사람들이 말했듯이 API를 가장 말하게하는 것은 추악합니다.


0

처음에는 선택 사항을 매개 변수로 전달하는 것이 좋았지 만 API 디자이너 관점에서 API 사용자 관점으로 전환하면 단점이 나타납니다.

예를 들어, 각 매개 변수가 선택적인 경우 계산 방법을 다음과 같이 자체 클래스로 변경하는 것이 좋습니다.

Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();

MyCalculator mc = new MyCalculator();
p1.map(mc::setP1);
p2.map(mc::setP2);
int result = mc.calculate();

0

저는이 질문이 어려운 사실보다는 의견에 관한 것임을 알고 있습니다. 그러나 나는 최근에 .net 개발자에서 Java 개발자로 옮겼으므로 최근에는 Optional Party에 합류했습니다. 또한 이것을 의견으로 언급하고 싶지만 포인트 수준으로 의견을 달 수 없으므로 대신 답변으로 입력해야합니다.

내가하고있는 일, 경험상 엄지 손가락의 역할을 잘 수행했습니다. 선택적 유형을 반환 유형으로 사용하고 선택적의 값과 날씨가 모두 필요하거나 선택 사항이 메소드 내에 값을 가지지 않은 경우 선택적을 매개 변수로만 사용합니다.

값만 신경 쓰면 메소드를 호출하기 전에 isPresent를 확인합니다. 값이 존재하는지에 따라 메소드 내에 로깅 또는 다른 논리가 있으면 선택 사항을 행복하게 전달합니다.


0

API 사용자와 API 개발자에 대한 요구 사항이 다르기 때문입니다.

개발자는 정확한 사양과 올바른 구현을 제공해야합니다. 따라서 개발자가 인수가 선택 사항임을 이미 알고있는 경우 구현은 널인지 또는 선택 사항인지에 상관없이 올바르게 처리해야합니다. API는 사용자에게 가능한 한 단순해야하며 null이 가장 간단합니다.

반면에 결과는 API 개발자에서 사용자에게 전달됩니다. 그러나 사양이 완전하고 장황하지만 사용자가이를 알지 못하거나 처리하기가 게으른 경우가 여전히 있습니다. 이 경우 선택적 결과는 사용자가 빈 결과를 처리하기 위해 추가 코드를 작성하도록합니다.


0

우선, 방법 3을 사용하는 경우 마지막 14 줄의 코드를 다음과 같이 바꿀 수 있습니다.

int result = myObject.calculateSomething(p1.orElse(null), p2.orElse(null));

작성한 네 가지 변형은 편의 방법입니다. 더 편리 할 때만 사용해야합니다. 그것은 또한 가장 좋은 방법입니다. 그런 식으로 API는 어느 멤버가 필요하고 어떤 멤버가 필요하지 않은지를 매우 명확합니다. 네 가지 방법을 쓰지 않으려면 매개 변수 이름을 지정하여 방법을 명확하게 설명 할 수 있습니다.

public int calculateSomething(String p1OrNull, BigDecimal p2OrNull)

이렇게하면 null 값이 허용됩니다.

의 사용은 p1.orElse(null)내가 그것을 피할 이유의 일부 옵션을 사용할 때 우리의 코드를 얻는 자세한 방법을 보여줍니다. 함수형 프로그래밍을 위해 옵션이 작성되었습니다. 스트림이 필요합니다. 함수형 프로그래밍에서 사용하지 않는 한 메소드는 Optional을 리턴하지 않아야합니다. 메소드와 같이 Optional.flatMap()선택적을 리턴하는 함수에 대한 참조가 필요한 메소드 가 있습니다 . 서명은 다음과 같습니다.

public <U> Optional<U> flatMap(Function<? super T, ? extends Optional<? extends U>> mapper)

따라서 이것이 Optional을 반환하는 메소드를 작성하는 유일한 이유입니다. 그러나 거기에서도 피할 수 있습니다. Optional을 반환하지 않는 getter는 flatMap ()과 같은 메소드에 함수를 올바른 유형으로 변환하는 다른 메소드로 랩핑하여 전달할 수 있습니다. 랩퍼 메소드는 다음과 같습니다.

public static <T, U> Function<? super T, Optional<U>> optFun(Function<T, U> function) {
    return t -> Optional.ofNullable(function.apply(t));
}

따라서 다음과 같은 게터가 있다고 가정하십시오. String getName()

다음과 같이 flatMap에 전달할 수 없습니다.

opt.flatMap(Widget::getName) // Won't work!

그러나 다음과 같이 전달할 수 있습니다.

opt.flatMap(optFun(Widget::getName)) // Works great!

함수형 프로그래밍 이외의 옵션은 피해야합니다.

Brian Goetz는 다음과 같이 말했을 때 가장 잘 말했습니다.

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;

1
이것이 Java에 추가 된 이유 중 하나입니다. 다른 많은 것들이 있습니다. Optional.map에 대한 단일 연속 호출로 데이터 구조를 가로 지르는 중첩 된 'if'문 체인을 대체하는 것이 개인적으로 가장 좋아하는 것입니다. Functional Languages ​​프로그래밍 세계는 단순히 널 점검을 대체하는 것 외에도 선택적에 대한 많은 흥미로운 용도를 가지고 있습니다.
Some Guy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.