Java 如何避免在方法链接中检查空值?
我需要检查某个值是否为null。如果不是null,那么只需将某个变量设置为true。这里没有其他声明。我有太多这样的状况检查 有没有办法在不检查所有方法返回值的情况下处理此空检查Java 如何避免在方法链接中检查空值?,java,exception-handling,nullpointerexception,Java,Exception Handling,Nullpointerexception,我需要检查某个值是否为null。如果不是null,那么只需将某个变量设置为true。这里没有其他声明。我有太多这样的状况检查 有没有办法在不检查所有方法返回值的情况下处理此空检查 if(country != null && country.getCity() != null && country.getCity().getSchool() != null && country.getCity().getSchool().getStudent() !
if(country != null && country.getCity() != null && country.getCity().getSchool() != null && country.getCity().getSchool().getStudent() != null .....) {
isValid = true;
}
我认为直接检查变量并忽略NullpointerException。这是一种好的做法吗
try{
if(country.getCity().getSchool().getStudent().getInfo().... != null)
} catch(NullPointerException ex){
//dont do anything.
}
不,在Java中,捕获NPE而不是空检查引用通常不是好的做法 如果您愿意,您可以使用:
if (Optional.ofNullable(country)
.map(Country::getCity)
.map(City::getSchool)
.map(School::getStudent)
.isPresent()) {
isValid = true;
}
或者干脆
boolean isValid = Optional.ofNullable(country)
.map(Country::getCity)
.map(City::getSchool)
.map(School::getStudent)
.isPresent();
如果这就是
isValid
应该检查的所有内容。您可以在这里使用Optional
,但它会在每个步骤创建一个可选对象
boolean isValid = Optional.ofNullable(country)
.map(country -> country.getCity()) //Or use method reference Country::getCity
.map(city -> city.getSchool())
.map(school -> school.getStudent())
.map(student -> true)
.orElse(false);
//OR
boolean isValid = Optional.ofNullable(country)
.map(..)
....
.isPresent();
作为
可选
的其他精细用法的替代方法,我们还可以使用带有供应商
变量args作为参数的实用方法。这是有道理的,因为我们在对象中没有很多嵌套级别要检查,但有很多字段要检查。
此外,当检测到
null
时,可以很容易地修改它以记录/处理某些内容
boolean isValid = isValid(() -> address, // first level
() -> address.getCity(), // second level
() -> address.getCountry(),// second level
() -> address.getStreet(), // second level
() -> address.getZip(), // second level
() -> address.getCountry() // third level
.getISO()
@SafeVarargs
public static boolean isValid(Supplier<Object>... suppliers) {
for (Supplier<Object> supplier : suppliers) {
if (Objects.isNull(supplier.get())) {
// log, handle specific thing if required
return false;
}
}
return true;
}
boolean-isValid=isValid(()->地址,//第一级
()->address.getCity(),//第二级
()->address.getCountry(),//第二级
()->address.getStreet(),//第二级
()->address.getZip(),//第二级
()->address.getCountry()//第三级
.getISO()
@安全变量
公共静态布尔值有效(供应商…供应商){
对于(供应商:供应商){
if(Objects.isNull(supplier.get())){
//记录,如果需要,处理特定的事情
返回false;
}
}
返回true;
}
假设您想添加一些跟踪,您可以这样写:
boolean isValid = isValid( Arrays.asList("address", "city", "country",
"street", "zip", "Country ISO"),
() -> address, // first level
() -> address.getCity(), // second level
() -> address.getCountry(),// second level
() -> address.getStreet(), // second level
() -> address.getZip(), // second level
() -> address.getCountry() // third level
.getISO()
);
@SafeVarargs
public static boolean isValid(List<String> fieldNames, Supplier<Object>... suppliers) {
if (fieldNames.size() != suppliers.length){
throw new IllegalArgumentException("...");
}
for (int i = 0; i < suppliers.length; i++) {
if (Objects.isNull(suppliers.get(i).get())) {
LOGGER.info( fieldNames.get(i) + " is null");
return false;
}
}
return true;
}
boolean isValid=isValid(Arrays.asList(“地址”、“城市”、“国家”),
“街道”、“邮编”、“国家ISO”),
()->地址,//第一级
()->address.getCity(),//第二级
()->address.getCountry(),//第二级
()->address.getStreet(),//第二级
()->address.getZip(),//第二级
()->address.getCountry()//第三级
.getISO()
);
@安全变量
公共静态布尔值有效(列出字段名、供应商…供应商){
if(fieldNames.size()!=suppliers.length){
抛出新的IllegalArgumentException(“…”);
}
对于(int i=0;iJava没有“空安全”操作,例如
您可以:
- 抓住NPE并忽略它
- 手动检查所有引用
- 根据其他答案使用可选选项
- 使用诸如XLST之类的工具
否则,如果您可以控制域对象,则可以重新设计类,以便从顶级对象中获得所需的信息(使Country
class执行所有空检查…)面向对象的方法是将isValid方法放在Country和其他类中。它不会减少空检查的数量,但每个方法只有一个,您不会重复它们
public boolean isValid() {
return city != null && city.isValid();
}
这假设验证在使用您所在国家/地区的任何地方都是相同的,但通常情况下都是如此。如果不是,则该方法应命名为hasStudent(),但这不太通用,并且您可能会在该国家/地区复制整个学校界面。例如,在另一个地方,您可能需要hasTeacher()或hasCourse()
另一种方法是使用空对象:
public class Country {
public static final Country NO_COUNTRY = new Country();
private City city = City.NO_CITY;
// etc.
}
我不确定在这种情况下是否更可取(严格来说,您需要一个子类来覆盖所有修改方法),Java 8的方法是在其他答案中使用Optional as方法,但我建议更全面地接受它:
private Optional<City> city = Optional.ofNullable(city);
public Optional<City> getCity() {
return city;
}
private Optional city=Optional.ofNullable(城市);
公共可选getCity(){
回归城市;
}
如果总是使用空对象而不是空对象(注意字段初始化),则只能使用空对象和可空对象。否则,您仍然需要空检查。因此,此选项可以避免空检查,但在其他位置,由于减少了空检查,您的代码会变得更加冗长
当然,正确的设计可能是在可能的情况下使用集合(而不是可选的)。一个国家有一套城市,一套城市有一套学校,有一套学生等等。你也可以看看vavr的选项,正如下面的文章所描述的,它比Java的可选选项更好,并且有更丰富的API
由于Java8中有optionalwell,因此在getCity()上可以得到null
值。这将导致NPE,你不知道什么是“代码> null <代码>,只是作为一个信息点:在创建这些类型的链之前你应该考虑。这个代码是一个巨大的红旗:如果你发现你自己写这么深的嵌套链,停止,重新考虑,并重新编写你的代码。最好的解决办法是消除这个问题。m:实现这些方法,使它们永远不会返回null。如果它们永远不会返回null,那么您就不必检查它。为什么null首先是一个合法的返回值?请注意,只有在调用代码之前,如果isValid
isfalse
,您的两个示例才是等效的!“不,在Java中允许NPE发生不是一个好的做法。”我不同意。如果传入的数据无效,应该抛出异常。A