我使用x!=null以避免NullPointerException。还有其他选择吗?
if (x != null) {
// ...
}
我使用x!=null以避免NullPointerException。还有其他选择吗?
if (x != null) {
// ...
}
当前回答
您可以使用FindBugs。他们还有一个Eclipse插件),可以帮助您查找重复的空检查(除其他外),但请记住,有时您应该选择防御性编程。还有Java合同可能会有所帮助。
其他回答
另一个建议是防御性地编程——类/函数提供已知且安全的默认值,并且为真正的错误/异常保留null。
例如,如果函数在出现问题时(例如将数字转换为字符串)返回空字符串,请让它们返回空字符串(“”)。在继续之前,您仍然必须测试返回值,但对于异常没有特殊情况。这种编程风格的另一个好处是,您的程序能够区分正常操作和异常,并做出相应的响应。
在Java8中,如果局部变量/字段/方法参数/方法返回类型从未赋值为null(并且不检查null),则可以使用类型T;如果可以为null,则可以键入Optional<T>。然后使用方法map处理T->,使用方法flatMap处理T->可选<R>:
class SomeService {
@Inject
private CompanyDao companyDao;
// return Optional<String>
public Optional<String> selectCeoCityByCompanyId0(int companyId) {
return companyDao.selectById(companyId)
.map(Company::getCeo)
.flatMap(Person::getHomeAddress)
.flatMap(Address::getCity);
}
// return String + default value
public String selectCeoCityByCompanyId1(int companyId) {
return companyDao.selectById(companyId)
.map(Company::getCeo)
.flatMap(Person::getHomeAddress)
.flatMap(Address::getCity)
.orElse("UNKNOWN");
}
// return String + exception
public String selectCeoCityByCompanyId2(int companyId) throws NoSuchElementException {
return companyDao.selectById(companyId)
.map(Company::getCeo)
.flatMap(Person::getHomeAddress)
.flatMap(Address::getCity)
.orElseThrow(NoSuchElementException::new);
}
}
interface CompanyDao {
// real situation: no company for such id -> use Optional<Company>
Optional<Company> selectById(int id);
}
class Company {
// company always has ceo -> use Person
Person ceo;
public Person getCeo() {return ceo;}
}
class Person {
// person always has name -> use String
String firstName;
// person can be without address -> use Optional<Address>
Optional<Address> homeAddress = Optional.empty();
public String getFirstName() {return firstName;}
public Optional<Address> getHomeAddress() {return homeAddress;}
}
class Address {
// address always contains country -> use String
String country;
// city field is optional -> use Optional<String>
Optional<String> city = Optional.empty();
String getCountry() {return country;}
Optional<String> getCity() {return city;}
}
public class Null {
public static void main(String[] args) {
String str1 = null;
String str2 = "";
if(isNullOrEmpty(str1))
System.out.println("First string is null or empty.");
else
System.out.println("First string is not null or empty.");
if(isNullOrEmpty(str2))
System.out.println("Second string is null or empty.");
else
System.out.println("Second string is not null or empty.");
}
public static boolean isNullOrEmpty(String str) {
if(str != null && !str.isEmpty())
return false;
return true;
}
}
输出
str1 is null or empty.
str2 is null or empty.
在上面的程序中,我们有两个字符串str1和str2。str1包含空值,str2为空字符串。
我们还创建了一个函数isNullOrEmpty(),顾名思义,它检查字符串是空还是空。它使用!=进行空检查null和字符串的isEmpty()方法。
简单地说,如果字符串不是null并且isEmpty()返回false,那么它既不是null也不是空的。否则,就是这样。
但是,如果字符串只包含空白字符(空格),则上述程序不会返回空。从技术上讲,isEmpty()看到它包含空格并返回false。对于带空格的字符串,我们使用string方法trim()来删除所有前导和尾随空格字符。
Java8现在有一个可选类,该类包装考虑中的对象,如果存在值,isPresent()将返回true,而get()则返回值。
http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html
如果不允许空值
如果从外部调用方法,请从以下内容开始:
public void method(Object object) {
if (object == null) {
throw new IllegalArgumentException("...");
}
然后,在该方法的其余部分中,您将知道该对象不为空。
如果它是一个内部方法(不是API的一部分),只需记录它不能为空,就可以了。
例子:
public String getFirst3Chars(String text) {
return text.subString(0, 3);
}
但是,如果您的方法只是传递值,而下一个方法传递值等,则可能会出现问题。在这种情况下,您可能需要检查上述参数。
如果允许为空
这真的取决于。如果发现我经常这样做:
if (object == null) {
// something
} else {
// something else
}
所以我分支,做两件完全不同的事情。没有难看的代码片段,因为我确实需要根据数据做两件不同的事情。例如,我应该处理输入,还是应该计算一个好的默认值?
实际上,我很少使用“if(object!=null&&…”这个成语。
如果你展示了你通常使用这个习语的例子,那么给你举例可能会更容易。