Я полагаю, что любой Java-разработчик столкнется с NPE (то есть NullPointerException), и чтобы избежать NPE, обычный метод состоит в том, чтобы оценить null перед доступом к объекту, то есть использовать оператор ветвления для оценкиif (xx != null)
. Однако слишком большое количество операторов ветвления (особенно в сочетании с бизнес-логикой) приведет к ухудшению читабельности и ремонтопригодности кода, поэтому его необходимо уменьшить. К счастью, Java8 предоставляет дополнительный инструмент, который может устранить большую часть пустых суждений и некоторые общие суждения.
Optional
Optional<T>
Представляет тип данных с нулевым значением или без него. Используйте Optional.ofNullable(), чтобы создать необязательный параметр, который принимает значение null. При использовании Optional.of() для создания необязательного параметра, если входящий параметр имеет значение null, NPE будет создан немедленно. В этой статье рассказывается не об использовании каждого метода в Необязательный, а о экземпляре Необязательный, заменяющий if в определенных ситуациях.
Альтернативная пустая ветка
Большинство пустых ветвей можно заменить на необязательные.
Object sth = ...;
// 为空抛出业务异常
if(sth == null){
throw new Exception...
}
// 或者提供默认值
if(sth == null){
sth = ...
}
// 从另外一个来源获取
if(sth == null){
sth = getFrom...()
}
// 不为空时,干点别的
if(sth != null){
...
}
// 不为空就,为空则(Java 9 以上适用)
if(sth != null){
...
}else{
...
}
Может быть рефакторинг с использованием соответствующего метода Optional:
// 为空抛出业务异常
Optional.ofNullable(...).orElseThrow(() -> new Exception...);
// 或者提供默认值
Optional.ofNullable(...).orElse(xxx);
// 从另外一个来源获取
Optional.ofNullable(...).orElseGet(() -> getFrom...());
// 不为空时,干点别的
Optional.ofNullable(...).ifPresent(x -> ...);
// 不为空就,为空则(Java 9 以上适用)
Optional.ofNullable(...).ifPresentOrElse(x -> ...,() -> ...);
Безопасные вызовы в цепочке
Object result = sth.getA().getB().getC().getD().getE();
Связанные вызовы действительно здорово писать, но если один из них будет нулевым, вы сойдете с ума 😫, а так как поле нулевого значения может быть неопределенным, вам может понадобиться вложить ветки или использовать сверхдлинную условную ветку Empty.
if(sth.getA() != null){
Object sth2 = sth.getA();
if(sth2.getB() != null){
...
}
}
// 或者
if(sth.getA() != null && sth.getA().getB() != null ...){
return ...
}
// 其他的不举例了
Этого можно избежать, используя метод карты option:
Optional.ofNullable(sth).map(xxx::getA).map(yyy::getB)...
Карта автоматически перенесет возвращаемое значение в Optional, а метод flatMap противоположен карте.Он принимает только ссылки на методы, возвращаемые как необязательные.. flatMap был введен для предотвращения многократного переноса, например, Optional
public class X{
public Optional<Y> getName(){
return ...
}
}
X sth = ...
Optional.ofNullable(sth).flatMap(X::getName)...
Замените некоторые ветви условного суждения
Необязательный также может заменить некоторые простые суждения об условиях Бина, используя метод фильтра.
XXX sth = ...
if(sth.getB() > 10){
return sth.getB().getC();
}
if(sth.getA() > 5){
throw new ...
}
// 使用Optional进行替代
// 注意这里这样子的话getC()的返回值就不能是null了,否则会抛出NoSuchElementException,要不把返回值类型改为Optional<T>?
return Optional.of(sth).map(XXX::getB).filter(x -> x > 10).map(XXX:getB).get();
// 注意这里是orElse,所以filter要反过来!
Optional.of(sth).map(XXX::getA).filter(x -> x <= 5).orElseThrow(() -> new ...);
Хорошая практика использования if
Даже там, где необходимо использовать if, есть приемы для оптимизации структуры кода. Один из принципов: минимизируйте вложенность кода, пишите короткие пути ветвления под if и, если необходимо, переворачивайте.
Одна из идей состоит в том, чтобы использовать if в качестве фильтра для оценки особых условий, своевременно оценивать «ненормальное состояние» и возвращать его.В качестве примера возьмем логин:
if(checkPassword(password,userInput)){
// 登录验证密码成功后可能会进行一堆操作
...
}else{
// 如果上面的代码非常多,不回顾下不知道是什么的else
throw new Exception("密码错误")
}
// 但如果是下面的写法,可能会好多了
if(!checkPassword(password,userInput)){
// 代码短的分支路径写在if下
// 调转if的条件,把验证密码错误作为一个特例进行过滤
throw new Exception("密码错误")
}
// 登录验证密码成功后的一堆操作,就不在分支里面,当作正常处理
...