我可以在使用我的方法时消除警告吗?
Can I silence warnings when USING my method?
我正在编写一个库方法来模拟 Java 中的 ?:
。
To be fair, I'm not sure how useful this is and I'm just testing it out personally for now.
/**
* 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,因为我手动检查了该方法中的每一行以确保在使用它时不会抛出 NPE,甚至由 running tests against it 进行了完整性检查。那么,如何在有人使用我的 nullCoalescing
方法时阻止此警告出现?
请注意,使用 nc
时 不会 发生这种情况(大概是因为它不会钻得更深?)。
问题源于您正在捕获可为 null 的 value
并无条件地在 lambda 表达式中对该引用调用方法。仅当 value
不是 null
时才会评估函数这一事实对审计工具不可见,因为您正在检查 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
,每个分析工具都应识别出 lambda 表达式正在访问非 null
值。即使没有深入研究该方法的工具也不会抱怨,就像使用它时一样
long l = nullCoalescing(value, nonNull -> nonNull.longValue(), 0L);
lambda 表达式不访问捕获的可为 null 的值,而仅访问 lambda 表达式的参数。作为奖励,它可能会更有效,因为非捕获 lambda 表达式将由单个实例表示,而不是在每次捕获时创建新实例(从当前实现开始)。
您甚至可以使用简化形式,例如
long l = nullCoalescing(value, nonNull -> nonNull, 0L);
或
long l = nullCoalescing(value, Long::longValue, 0L);
顺便说一句,上面的代码还解决了另外两个问题。通过插入单个 <?>
,您可以摆脱 @SuppressWarnings("unchecked")
,通常,通过在用 [ 注释的方法中记录和返回 null
来处理非法状态不是一个好主意=24=],情况比以前更糟了……
我正在编写一个库方法来模拟 Java 中的 ?:
。
To be fair, I'm not sure how useful this is and I'm just testing it out personally for now.
/**
* 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,因为我手动检查了该方法中的每一行以确保在使用它时不会抛出 NPE,甚至由 running tests against it 进行了完整性检查。那么,如何在有人使用我的 nullCoalescing
方法时阻止此警告出现?
请注意,使用 nc
时 不会 发生这种情况(大概是因为它不会钻得更深?)。
问题源于您正在捕获可为 null 的 value
并无条件地在 lambda 表达式中对该引用调用方法。仅当 value
不是 null
时才会评估函数这一事实对审计工具不可见,因为您正在检查 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
,每个分析工具都应识别出 lambda 表达式正在访问非 null
值。即使没有深入研究该方法的工具也不会抱怨,就像使用它时一样
long l = nullCoalescing(value, nonNull -> nonNull.longValue(), 0L);
lambda 表达式不访问捕获的可为 null 的值,而仅访问 lambda 表达式的参数。作为奖励,它可能会更有效,因为非捕获 lambda 表达式将由单个实例表示,而不是在每次捕获时创建新实例(从当前实现开始)。
您甚至可以使用简化形式,例如
long l = nullCoalescing(value, nonNull -> nonNull, 0L);
或
long l = nullCoalescing(value, Long::longValue, 0L);
顺便说一句,上面的代码还解决了另外两个问题。通过插入单个 <?>
,您可以摆脱 @SuppressWarnings("unchecked")
,通常,通过在用 [ 注释的方法中记录和返回 null
来处理非法状态不是一个好主意=24=],情况比以前更糟了……