public static void main(String[] args) {
Manager manager1 = new Manager();
Manager manager2 = null;
// both line 1 and line 2 are ok
NullUtils.objectNullFieldNull(manager1, () -> manager1.getName(), "");
NullUtils.objectNullFieldNull(manager1, manager1::getName, "");
// line 1 is ok but line 2 will throw NullPointerException
NullUtils.objectNullFieldNull(manager2, () -> manager2.getName(), "");
NullUtils.objectNullFieldNull(manager2, manager2::getName, "");
}
众所周知,我们可以在Java中使用xxx::yyy
代替() -> xxx.yyy()
,但是如果xxx
为null,则它们将有所不同。
使用的版本::
将引发NullPointerException,但() -> xxx.yyy()
在实际调用该函数之前不会引发异常。
为什么是这样?
我使用IntelliJ IDEA进行编码,如果可以使用::
代替->
,则IDE将显示警告,告诉我将其更改为使用::
(即使那样会导致NullPointerException)。
我该如何解决?
其他相关代码:
public class NullUtils {
public static <O, R> R objectNullFieldNull(O o, Supplier<R> supplier, R orv) {
return Objects.isNull(o) ? orv : objectNull(supplier.get(), orv);
}
public static <O> O objectNull(O original, O target) {
return Objects.isNull(original) ? target : original;
}
}
@Data
@Builder(toBuilder = true)
@NoArgsConstructor
@AllArgsConstructor
public class Manager {
private String code;
private String name;
private String mobile;
}
如你所见,如果xxx
为null,则() -> xxx.yyy()
创建一个函数,该函数将在调用NPE时抛出NPE,但在创建但未调用该函数时不抛出异常。但是xxx::yyy
立即抛出NPE。因此,如果你要在两者之间进行选择并且不想抛出NPE,请使用该->
版本。
但是,还有另一种选择。你的objectNullFieldNull
方法编写起来有些混乱,因为作为第一个参数传递的对象与作为第二个参数传递的供应商没有明确的关系。在我看来,第二个参数成为使用第一个参数的函数似乎更自然,如下所示:
public static <O, R> R objectNullFieldNull(O o, Function<? super O, R> field, R orv) {
return o==null ? orv : objectNull(field.apply(o), orv);
}
你可以像这样使用它:
objectNullFieldNull(manager2, Manager::getName, "")
或像这样
objectNullFieldNull(manager2, m -> m.getName(), "")
如果NPEmanager2
为null,NPE也不会。
Manager::getName
是一个Function<Manager, String>
接受管理器(或null)作为其参数,并尝试对其进行调用的getName()
。请参见方法参考:对特定类型的任意对象的实例方法的引用。
谢谢你解决了我的问题
我向您建议了另一个静态函数〜我还有一个问题:为什么
Manager::getName
可以使用Function<? super O, R> field
?是因为Class的方法真值第一个参数是this
?我从不使用Class :: ClassMethod,参数如何匹配?能否请您提供一些我可以自己学习的参考链接或统计信息,或者给我一些我可以在线搜索的关键字,谢谢〜
docs.oracle.com/javase/tutorial/java/javaOO / ...
非常感谢@khelwood