1

자바에서 ?:을 에뮬레이트하는 라이브러리 메소드를 작성하고 있습니다.내 방법을 사용할 때 경고를 없앨 수 있습니까?

공정하게 말해서 나는 이것이 얼마나 유용한 지 확신 할 수 없으며 지금은 개인적으로 테스트하고 있습니다.

/** 
* Shorthand for {@link #nullCoalescing(Object, Supplier, Object)} 
*/ 
@NotNull 
public static <RawType, BackupType> BackupType nc(
     @Nullable RawType possiblyNullValueContainer, 
     @NotNull Supplier<BackupType> ifNotNull, 
     @NotNull BackupType nonNullBackup) { 
    return nullCoalescing(possiblyNullValueContainer, ifNotNull, nonNullBackup); 
} 

/** 
* Null Coalescing method: If {@code possiblyNullValueContainer} is {@code null}, {@code nonNullBackup} is returned; 
* else, {@code ifNotNull} is invoked and its result returned. The only caveat occurs when {@code 
* possiblyNullValueContainer} is a non-null {@link Optional}, wherein its {@link Optional#isPresent() isPresent()} 
* method is checked after discovering that it itself is not null. 
* 
* @param possiblyNullValueContainer The possibly-null value to check, or an {@link Optional} whose internal value 
*         is to be checked. 
* @param ifNotNull     If {@code possiblyNullValueContainer} is not {@code null}, this is invoked and 
*         its result returned. The intended use is that this references a method that can 
*         be called on the aforementioned object, like {@code() -> 
*         possiblyNullValueContainer.toString()}. If this is {@code null}, you're just 
*         being silly and {@code null} will be returned. 
* @param nonNullBackup    If {@code possiblyNullValueContainer} is {@code null}, this is returned. 
* @param <RawType>     The type of value to check for nullability 
* @param <BackupType>    The type of the backup values, which should not be null. 
* 
* @return Pretty much {@code possiblyNullValueContainer ? ifNotNull() : nonNullBackup} 
*/ 
@NotNull 
@SuppressWarnings("unchecked") // manually type-checked 
public static <RawType, BackupType> BackupType nullCoalescing(
     @Nullable RawType possiblyNullValueContainer, 
     @NotNull Supplier<BackupType> ifNotNull, 
     @NotNull BackupType nonNullBackup) { 
    if (null == possiblyNullValueContainer) { 
     return nonNullBackup; 
    } else if (possiblyNullValueContainer instanceof Optional) { 
     // If they pass us an Optional, they must want us to check if it has a value inside rather than itself 
     Optional nonNullOpt = (Optional) possiblyNullValueContainer; 
     if (!nonNullOpt.isPresent()) { 
      return nonNullBackup; 
     } 
    } 

    if (null == ifNotNull) { 
     Logger.getGlobal().severe("What are you doing?!"); 
     return null; 
    } else { 
     return ifNotNull.get(); 
    } 
} 

이는 등처럼 사용된다 : 잘 작동

// kinda like int i = value ?: 0 
int i = nc(value,() -> value.intValue(), 0) 

// less useful, I know, but still supported 
String s = nc(optional ,() -> optional.get(), "simple"); 

합니다. 내가 좋아하는, 전체 메소드 이름을 사용할 때 문제가 온다 :

long l = nullCoalescing(value,() -> value.longValue(), 0L) 

나는이 경고를 얻을 : 내가 수동으로 각각의 모든 라인을 확인하기 때문에,

Unboxing of 'nullCoalescing(value,() -> value.longValue(), 0L)' may produce 'java.lang.NullPointerException'

명확 bubkus한다 메소드를 사용하는 동안 NPE가 던져 질 수 없도록하고, 심지어는 running tests against it으로 온건성 검사를하는 방법을 사용합니다. 그래서 누군가 내 nullCoalescing 방법을 사용할 때마다이 경고가 나타나지 않게하려면 어떻게해야합니까? nc를 사용하는 경우

참고이가하는 발생하지 (그것이 어떤 깊이를 드릴하지 않습니다 아마도 때문에?).

답변

2

이 문제는 nullable value을 캡처하고 람다 식 내에서 해당 참조에 대해 무조건 메서드를 호출한다는 사실 때문에 발생합니다. valuenull이 아닌 경우에만 기능을 평가한다는 사실은 캡처 된 값이 아닌 possiblyNullValueContainer 매개 변수를 검사 할 때 감사 도구에 표시되지 않습니다.이 값은 동일한 참조를 포함하지만 감사 기능을 초과하는 것으로 보입니다.

는 어차피 다른 설계를 권장합니다

@NotNull 
public static <RawType, BackupType> BackupType nullCoalescing(
     @Nullable RawType possiblyNullValueContainer, 
     @NotNull Function<RawType,BackupType> ifNotNull, 
     @NotNull BackupType nonNullBackup) { 

    Objects.requireNonNull(ifNotNull);// don't provide fall-backs for illegal use 
    Objects.requireNonNull(nonNullBackup); // be explicit 

    if (null == possiblyNullValueContainer) { 
     return nonNullBackup; 
    } 
    else if (possiblyNullValueContainer instanceof Optional) { 
     // If they pass us an Optional, 
     // they want us to check if it has a value inside rather than itself 
     Optional<?> nonNullOpt = (Optional)possiblyNullValueContainer; 
     if (!nonNullOpt.isPresent()) { 
      return nonNullBackup; 
     } 
    } 
    return ifNotNull.apply(possiblyNullValueContainer); 
} 

null 대해 확인 된 기준을 수신하는 Function를 사용하여 모든 분석 도구는 람다 식 비 null 값에 액세스하고 있음을 인식해야한다. 심지어 도구가 아닌 div 캡처 널 값을 액세스하지

long l = nullCoalescing(value, nonNull -> nonNull.longValue(), 0L); 

같은 람다 식을 이용한 경우와 같이, 불평하는 메소드에 보내고 있지만, 람다 식의 매개 변수 만. 보너스 포인트로서, 현재 캡슐화 할 때마다 새로운 인스턴스를 생성하는 대신 캡쳐되지 않은 람다식이 단일 인스턴스로 표현되므로 잠재적으로보다 효율적입니다.

단순한 형식을 사용할 수도 있습니다. 그런데

long l = nullCoalescing(value, nonNull -> nonNull, 0L); 

또는

long l = nullCoalescing(value, Long::longValue, 0L); 

은, 위의 코드뿐만 아니라 다른 두 가지 문제를 해결합니다.하나의 <?>을 삽입함으로써, 당신은 @SuppressWarnings("unchecked") 일반적으로 제거 할 수, ... 이전보다 상황이 더 악화 만들기, 로깅 및 @NotNull 주석 방법에 null을 반환하여

을 불법 상태를 처리 할 수있는 좋은 생각이 아니다
관련 문제