컨텍스트 : 나는 menbers가있는 패밀리를 반환하는 웹 서비스가 있습니다. 가족에게는 항상 아버지와 어머니, 자녀가 없거나 여러 개의 자녀가 있습니다. 서비스는 wsdl에 의해 아래에서 설명됩니다.웹 서비스의 반환이 Optional을 사용하여 null인지 확인하고 noSuchElementException을 피하는 방법을 고차 함수를 사용하는 방법
목적 : Java 8에서 선택 사항을 효과적으로 사용하고 null을 확인하는 고전적인 방법을 사용하지 않겠습니다.
@Test
public void test1() {
Family f = helloWorldClientImplBean.allFamily();
f.getChildren().stream().filter(x -> x.getFirstName().equalsIgnoreCase("John")).findFirst()
.ifPresent(y -> System.out.println(y.getLastName()));
}
내가 테스트하고 나는 것을 볼 수 있습니다 : 고전, 나는 우리가 내가 웹 서비스는 항상 가족을 반환한다고 가정하면 자바 7
까지 달성하는 데 사용 된 방법을 의미하는이 충분하다 , 나는 가족이 봉사함으로써 응답을받는 한, 나는 자녀가 있는지 없는지 상관없이 완벽하게 작동 할 것입니다. 나는 아래의 서비스 구현에서 oldSon 및 youngSon 코드에 null 예외가 전혀 없다고 주석을 달았습니다.
서비스가 null을 반환하면 문제가 발생합니다.
블로그를 읽고 그것에 대한 토론을 마친 후 서비스 반환이 null인지 제대로 확인하는이 코드에 도달했습니다.
@Test
public void testWorkingButSeemsOdd() {
//Family f = helloWorldClientImplBean.allFamily();
Family f = null; //to make simple the explanation
Optional<Family> optFamily = Optional.ofNullable(f);
if (optFamily.isPresent()) {
optFamily.filter(Objects::nonNull).map(Family::getChildren).get().stream().filter(Objects::nonNull)
.filter(x -> x.getFirstName().equalsIgnoreCase("John")).findFirst()
.ifPresent(y -> System.out.println("Optional: " + y.getLastName()));
}
나 이러한 방법 중 하나 (모두가 failling하고 있지만 나는 그들이 내가 할 노력하고 무엇을 보여줄 수 있다고 생각) 것 더 깨끗한 것이 무엇 : 여기에 내가 시도
// f는 매핑
@Test
public void testFilterNonNull() {
Family f = null;
Optional.ofNullable(f).filter(Objects::nonNull).map(Family::getChildren).get().stream().filter(Objects::nonNull)
.filter(x -> x.getFirstName().equalsIgnoreCase("John")).findFirst()
.ifPresent(y -> System.out.println(y.getLastName()));
}
내가 컴파일되지 않습니다 다음을 알고 있지만 나는 비슷한에 도달 할 수 있습니다 생각하기 전에 null가 아닌 경우, 필터링하는
@Test
@Ignore
public void testOptionalNullable() {
Family f = helloWorldClientImplBean.allFamily();
Optional.ofNullable(f).orElse(System.out.println("Family is null")).map(Family::getChildren).get().stream().filter(Objects::nonNull)
.filter(x -> x.getFirstName().equalsIgnoreCase("John")).findFirst()
.ifPresent(y -> System.out.println(y.getLastName()));
}
01 23,516,
WSDL
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions targetNamespace="http://codenotfound.com/services/helloworld"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://codenotfound.com/services/helloworld"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
name="HelloWorld">
<wsdl:types>
<schema targetNamespace="http://codenotfound.com/services/helloworld"
xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://codenotfound.com/services/helloworld"
elementFormDefault="qualified" attributeFormDefault="unqualified"
version="1.0">
<element name="family">
<complexType>
<sequence>
<element name="father" type="tns:persontype" minOccurs="1"
maxOccurs="1" />
<element name="mother" type="tns:persontype" minOccurs="1"
maxOccurs="1" />
<element name="children" type="tns:persontype" minOccurs="0"
maxOccurs="unbounded" />
</sequence>
</complexType>
</element>
<complexType name="persontype">
<sequence>
<element name="firstName" type="xsd:string" />
<element name="lastName" type="xsd:string" />
</sequence>
</complexType>
<element name="EmptyParameter" type="tns:voidType" />
<complexType name="voidType">
<sequence />
</complexType>
</schema>
</wsdl:types>
<!-- Message -->
<wsdl:message name="emptyRequest">
<wsdl:part name="emptyParameter" element="tns:EmptyParameter" />
</wsdl:message>
<wsdl:message name="allFamiliesResponse">
<wsdl:part name="allFamiliesResponse" element="tns:family" />
</wsdl:message>
<!-- PortType -->
<wsdl:operation name="allFamilies">
<wsdl:input message="tns:emptyRequest" />
<wsdl:output message="tns:allFamiliesResponse"></wsdl:output>
</wsdl:operation>
</wsdl:portType>
<!-- Binding -->
<wsdl:binding name="HelloWorld_Binding" type="tns:HelloWorld_PortType">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="allFamilies">
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="HelloWorld_Service">
<wsdl:port name="HelloWorld_Port" binding="tns:HelloWorld_Binding">
<soap:address location="http://localhost:9090/cnf/services/helloworld" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
서비스 구현의
관련 부분 :
그래서, 내 바로 질문입니다@Override
public Family allFamilies(VoidType emptyParameter) {
ObjectFactory factory = new ObjectFactory();
Family result = factory.createFamily();
Persontype father = new Persontype();
father.setFirstName("Jose");
father.setLastName("Pereira");
Persontype mother = new Persontype();
mother.setFirstName("Maria");
mother.setLastName("Pereira");
result.setFather(father);
result.setMother(mother);
Persontype olderSon = new Persontype();
olderSon.setFirstName("John");
olderSon.setLastName("Pereira");
Persontype youngerSon = new Persontype();
youngerSon.setFirstName("Ana");
youngerSon.setLastName("Pereira");
result.getChildren().add(olderSon);
result.getChildren().add(youngerSon);
return result;
}
: WSDL 및 구현 전술 내 시나리오에 따라이 있는지 확인하기 위해 정말 유일한 방법입니다 우리가 고전적인 null 검사 (if (f! = null) {...)와 매우 유사한 방식으로 isPresent()를 사용하여 웹 서비스로부터의 반환 값은 null이됩니까?
나는 여기입니다 의견을 기반으로 질문 ... 당신은'IF-else' * 아니라-*은'Optional.ofNullable'로, 그것의 단지를 가지고 있다고 생각 선택의 문제. 문제는'if/else'와'{}'블록 내부의 스트림 작업에 대한 것이고, 어떻게 든 더 깨끗해 보입니다. – Eugene
'Optional'에'.filter (Objects :: nonNull)'를 호출하면 어떤 의미가 있습니다. 'Optional'의 요점은 캡슐화 된 객체가 절대 null이 될 수 없다는 것입니다. 선택적 요소가 비어 있으면 필터 조건자가 평가되지 않습니다. 그래서'.filter (Objects :: nonNull)'의 효과는'.filter (x -> true)'와 동일합니다. 두 경우 모두 원래의 옵션을 되 돌리는 것입니다. – Holger
가능한 경우,'helloWorldClientImplBean.allFamily()'를 수정하여 nullable'Family' 참조 대신'Optional'을 반환하는 것이 좋습니다.결과를'Optional.ofNullable'에 래핑하는 대신에,'Optional'의 생성을 피 호출자로 푸시하는 것이 좋을 것입니다. 여기에 표시된 호출 코드는'Optional'을 직접 사용하기 쉽습니다. 이것은 발신자가 널 체크를하거나 자신의'Optional' 포장을 강요하는 것이 바람직합니다. –