java lambda :: expression 有什么问题?为什么 ? :: 和普通表达式之间有什么区别?
what wrong with java lambda :: expression ? why ? what diff between :: and normal expression?
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,但如果创建该函数则不会抛出异常并且没有叫。但是 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(), "")
如果 manager2
为空,NPE 也不会。
Manager::getName
是一个 Function<Manager, String>
,它接受一个管理器(或 null)作为其参数,并尝试对其调用 getName()
。请参阅 method references:引用特定类型的任意对象的实例方法。
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,但如果创建该函数则不会抛出异常并且没有叫。但是 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(), "")
如果 manager2
为空,NPE 也不会。
Manager::getName
是一个 Function<Manager, String>
,它接受一个管理器(或 null)作为其参数,并尝试对其调用 getName()
。请参阅 method references:引用特定类型的任意对象的实例方法。