자바 "?" null 검사 연산자-무엇입니까? (삼항이 아닙니다!)
나는 slashdot 이야기에서 링크 된 기사를 읽고 있었고,이 작은 정보를 발견했습니다.
끝없는 포인터 테스트를위한 속기 구문을 제공하여 널 포인터 검사를 더 쉽게 만드는 최신 버전의 Java를 사용하십시오. 각 메서드 호출에 물음표를 추가하기 만하면 null 포인터에 대한 테스트가 자동으로 포함되어 다음과 같이 쥐의 if-then 문을 대체합니다.
public String getPostcode(Person person) { String ans= null; if (person != null) { Name nm= person.getName(); if (nm!= null) { ans= nm.getPostcode(); } } return ans }
이것으로 :
public String getFirstName(Person person) { return person?.getName()?.getGivenName(); }
나는 인터넷을 샅샅이 뒤졌고 (좋아, "자바 물음표"에 대한 인터넷 검색에 적어도 15 분을 보냈다) 아무것도 얻지 못했다. 그래서, 내 질문 : 이것에 대한 공식 문서가 있습니까? C #에 유사한 연산자 ( "??"연산자)가 있지만 작업중인 언어에 대한 문서를 얻고 싶습니다. 아니면 제가 사용한 삼항 연산자를 사용하고 있습니까? 본 적없는.
감사!
편집 : 기사 링크 : http://infoworld.com/d/developer-world/12-programming-mistakes-avoid-292
원래 아이디어는 그루비에서 나왔습니다. 프로젝트 코인 : https://wiki.openjdk.java.net/display/Coin/2009+Proposals+TOC(Elvis 및 기타 Null-Safe 연산자)의 일부로 Java 7 용으로 제안 되었지만 아직 승인되지 않았습니다. .
관련 엘비스 연산자는? 만들기 위해 제안되었다 x ?: y
위한 속기 x != null ? x : y
x는 복잡한 표현 인 경우 특히 유용합니다.
이 구문은 Java에 존재하지 않으며 내가 아는 향후 버전에 포함될 예정이 아닙니다.
Java 7에 대한 제안이 있었지만 거부되었습니다.
http://tech.puredanger.com/java7/#null
"?"부족을 해결하는 한 가지 방법 try-catch의 오버 헤드없이 Java 8을 사용하는 연산자 ( NullPointerException
언급 한대로 다른 곳에서 시작된 것을 숨길 수도 있음 )는 Java-8-Stream 스타일의 "파이프"메서드에 대한 클래스를 만드는 것입니다.
public class Pipe<T> {
private T object;
private Pipe(T t) {
object = t;
}
public static<T> Pipe<T> of(T t) {
return new Pipe<>(t);
}
public <S> Pipe<S> after(Function<? super T, ? extends S> plumber) {
return new Pipe<>(object == null ? null : plumber.apply(object));
}
public T get() {
return object;
}
public T orElse(T other) {
return object == null ? other : object;
}
}
그러면 주어진 예는 다음과 같습니다.
public String getFirstName(Person person) {
return Pipe.of(person).after(Person::getName).after(Name::getGivenName).get();
}
[편집하다]
더 깊이 생각해 보면 표준 Java 8 클래스를 사용해야 만 실제로 동일한 결과를 얻을 수 있다는 것을 알았습니다.
public String getFirstName(Person person) {
return Optional.ofNullable(person).map(Person::getName).map(Name::getGivenName).orElse(null);
}
이 경우 매개 변수로 전달하는 "<no first name>"
대신 기본값 (예 :)을 선택할 수도 있습니다 .null
orElse
참조 : https://blogs.oracle.com/darcy/project-coin:-the-final-five-or-so (특히 "Elvis 및 기타 널 안전 연산자").
그 결과이 기능은 Java 7 용으로 고려되었지만 포함되지 않았습니다.
이것은 실제로 Groovy의 안전 역 참조 연산자 입니다. 순수한 자바에서는 사용할 수 없기 때문에 (슬프게도) 게시물이 잘못되었습니다 (또는 Groovy가 "Java의 최신 버전"이라고 주장하는 경우 약간 오해의 소지가 있음).
Java 8 람다를 사용하여 거의 예쁘게이 문제를 해결하는 util 메서드를 정의 할 수 있습니다.
이것은 H-MAN 솔루션 의 변형 이지만 여러 인수가있는 오버로드 된 메서드를 사용하여 NullPointerException
.
이 솔루션이 멋지다고 생각하더라도 헬더 페레이라의 세컨드 솔루션을 선호한다고 생각 합니다.
void example() {
Entry entry = new Entry();
// This is the same as H-MANs solution
Person person = getNullsafe(entry, e -> e.getPerson());
// Get object in several steps
String givenName = getNullsafe(entry, e -> e.getPerson(), p -> p.getName(), n -> n.getGivenName());
// Call void methods
doNullsafe(entry, e -> e.getPerson(), p -> p.getName(), n -> n.nameIt());
}
/** Return result of call to f1 with o1 if it is non-null, otherwise return null. */
public static <R, T1> R getNullsafe(T1 o1, Function<T1, R> f1) {
if (o1 != null) return f1.apply(o1);
return null;
}
public static <R, T0, T1> R getNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, R> f2) {
return getNullsafe(getNullsafe(o0, f1), f2);
}
public static <R, T0, T1, T2> R getNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, T2> f2, Function<T2, R> f3) {
return getNullsafe(getNullsafe(o0, f1, f2), f3);
}
/** Call consumer f1 with o1 if it is non-null, otherwise do nothing. */
public static <T1> void doNullsafe(T1 o1, Consumer<T1> f1) {
if (o1 != null) f1.accept(o1);
}
public static <T0, T1> void doNullsafe(T0 o0, Function<T0, T1> f1, Consumer<T1> f2) {
doNullsafe(getNullsafe(o0, f1), f2);
}
public static <T0, T1, T2> void doNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, T2> f2, Consumer<T2> f3) {
doNullsafe(getNullsafe(o0, f1, f2), f3);
}
class Entry {
Person getPerson() { return null; }
}
class Person {
Name getName() { return null; }
}
class Name {
void nameIt() {}
String getGivenName() { return null; }
}
이것이 효과가 있을지 모르겠습니다. 예를 들어, 사람 참조가 null 인 경우 런타임은이를 무엇으로 대체합니까? 새로운 사람? 이 경우 Person이 예상 할 수있는 기본 초기화가 필요합니다. 널 참조 예외를 피할 수 있지만 이러한 유형의 설정을 계획하지 않은 경우 여전히 예측할 수없는 동작이 발생합니다.
? C #의 연산자는 "통합"연산자로 가장 잘 불릴 수 있습니다. 여러 표현식을 연결할 수 있으며 null이 아닌 첫 번째 표현식을 반환합니다. 불행히도 Java에는 없습니다. 가장 좋은 방법은 삼항 연산자를 사용하여 null 검사를 수행하고 체인의 멤버가 null 인 경우 전체 표현식에 대한 대안을 평가하는 것입니다.
return person == null ? ""
: person.getName() == null ? ""
: person.getName().getGivenName();
try-catch를 사용할 수도 있습니다.
try
{
return person.getName().getGivenName();
}
catch(NullReferenceException)
{
return "";
}
Java에는 정확한 구문이 없지만 JDK-8부터는 다양한 메서드를 사용할 수있는 Optional API 가 있습니다. 따라서 null 조건부 연산자를 사용하는 C # 버전 :
return person?.getName()?.getGivenName();
선택적 API를 사용하여 Java에서 다음과 같이 작성할 수 있습니다 .
return Optional.ofNullable(person)
.map(e -> e.getName())
.map(e -> e.getGivenName())
.orElse(null);
person
, getName
또는 중 하나 getGivenName
가 null이면 null이 반환됩니다.
Java 8에서 null-safe 호출이 있습니다.
public void someMethod() {
String userName = nullIfAbsent(new Order(), t -> t.getAccount().getUser()
.getName());
}
static <T, R> R nullIfAbsent(T t, Function<T, R> funct) {
try {
return funct.apply(t);
} catch (NullPointerException e) {
return null;
}
}
누군가 이전 자바 버전에 대한 대안을 찾고 있다면 내가 작성한 다음을 시도해 볼 수 있습니다.
/**
* Strong typed Lambda to return NULL or DEFAULT VALUES instead of runtime errors.
* if you override the defaultValue method, if the execution result was null it will be used in place
*
*
* Sample:
*
* It won't throw a NullPointerException but null.
* <pre>
* {@code
* new RuntimeExceptionHandlerLambda<String> () {
* @Override
* public String evaluate() {
* String x = null;
* return x.trim();
* }
* }.get();
* }
* <pre>
*
*
* @author Robson_Farias
*
*/
public abstract class RuntimeExceptionHandlerLambda<T> {
private T result;
private RuntimeException exception;
public abstract T evaluate();
public RuntimeException getException() {
return exception;
}
public boolean hasException() {
return exception != null;
}
public T defaultValue() {
return result;
}
public T get() {
try {
result = evaluate();
} catch (RuntimeException runtimeException) {
exception = runtimeException;
}
return result == null ? defaultValue() : result;
}
}
제공 한 코드를 테스트 할 수 있으며 구문 오류가 발생하므로 Java에서는 지원되지 않습니다. Groovy는이를 지원하며 Java 7 용으로 제안되었지만 포함되지 않았습니다.
그러나 Java 8에서 제공하는 옵션을 사용할 수 있습니다. 이는 유사한 행에서 무언가를 달성하는 데 도움이 될 수 있습니다. https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html
Android는 설치된 OS가 24보다 크지 않으면 Lambda 함수를 지원하지 않으므로 리플렉션을 사용해야합니다.
// Example using doIt function with sample classes
public void Test() {
testEntry(new Entry(null));
testEntry(new Entry(new Person(new Name("Bob"))));
}
static void testEntry(Entry entry) {
doIt(doIt(doIt(entry, "getPerson"), "getName"), "getName");
}
// Helper to safely execute function
public static <T,R> R doIt(T obj, String methodName) {
try {
if (obj != null)
return (R)obj.getClass().getDeclaredMethod(methodName).invoke(obj);
} catch (Exception ignore) {
}
return null;
}
// Sample test classes
static class Entry {
Person person;
Entry(Person person) { this.person = person; }
Person getPerson() { return person; }
}
static class Person {
Name name;
Person(Name name) { this.name = name; }
Name getName() { return name; }
}
static class Name {
String name;
Name(String name) { this.name = name; }
String getName() {
System.out.print(" Name:" + name + " ");
return name;
}
}
}
이것이 성능 문제가 아니라면 다음과 같이 작성할 수 있습니다.
public String getFirstName(Person person) {
try {
return person.getName().getGivenName();
} catch (NullPointerException ignored) {
return null;
}
}
참고URL : https://stackoverflow.com/questions/4390141/java-operator-for-checking-null-what-is-it-not-ternary
'Development Tip' 카테고리의 다른 글
Objective C의 iPhone 개발에서 "대리자"는 무엇입니까? (0) | 2020.11.03 |
---|---|
Android 레이아웃 오른쪽 정렬 (0) | 2020.11.03 |
SQL Server-부울 리터럴? (0) | 2020.11.03 |
Java 8의 기본 Xmxsize (0) | 2020.11.03 |
Xcode 스토리 보드 : 내부 오류. (0) | 2020.11.03 |