1

私は?:をJavaでエミュレートするライブラリメソッドを書いています。私のメソッドを使用しているときに警告を消すことはできますか?

これはどれくらい便利なのかよく分かりませんが、今は個人的にテストしています。

/** 
* 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) 

と私は、この警告を得る:私は手動でその中にそれぞれ、すべての行をチェックしているため、明確であるbubkus

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

をNPEを使用している間に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にならないキャプチャNULL可能値にアクセスしない

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

のようなラムダ式を、それを使用するときのように、文句を言わないだろう方法にするが、ラムダ式のパラメータのみ。ボーナスポイントとして、非キャプチャラムダ式は各キャプチャで新しいインスタンスを作成するのではなく、1つのインスタンスで表現されるため、潜在的により効率的です(現在の実装の場合)。

単純なフォームを使用することもできます。

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

又は

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

ところで、上記のコードは、同様に他の二つの問題を解決します。単一<?>を挿入することにより、あなたは@SuppressWarnings("unchecked")を取り除くことができ、一般的に、伐採による不正な状態を処理し、@NotNullで注釈が付け方法でnullを返す、以前より状況はさらに悪化することをお勧めではありません...

関連する問題