避免Java中的NullPointerException
我使用避免Java中的NullPointerException,java,nullpointerexception,null,Java,Nullpointerexception,Null,我使用对象!=空值需要避免很多 什么是替代方案: if(someobject!=null){ someobject.doCalc(); } < /代码> 而不是空对象模式——它有它的用途——您可以考虑null对象是bug的情况。 当抛出异常时,检查堆栈跟踪并处理错误。 如果你认为一个对象不应该是null(或者它是一个bug),那么使用一个断言。 如果您的方法不接受null参数,请在javadoc中声明并使用断言 您必须检查对象!=仅当要处理对象可能为null的情况时才为null 有人建议在Ja
对象!=空值
需要避免很多
什么是替代方案:
if(someobject!=null){
someobject.doCalc();
}
< /代码> 而不是空对象模式——它有它的用途——您可以考虑null对象是bug的情况。
当抛出异常时,检查堆栈跟踪并处理错误。
如果你认为一个对象不应该是null(或者它是一个bug),那么使用一个断言。
- 如果您的方法不接受null参数,请在javadoc中声明并使用断言
您必须检查对象!=仅当要处理对象可能为null的情况时才为null
有人建议在Java7中添加新注释,以帮助处理null/notnull参数:
有时,您可以使用对其参数进行操作的方法来定义对称操作:
a.f(b); <-> b.f(a);
a.f(b);b、 f(a);
如果你知道b永远不能为null,你可以交换它。这对平等者最有用:
而不是foo.equals(“bar”)代码>最好做“bar”。等于(foo)代码>根据要检查的对象类型,您可能能够使用apache commons中的某些类,例如:和
例如:
String foo;
...
if( StringUtils.isBlank( foo ) ) {
///do something
}
或者(取决于您需要检查的内容):
StringUtils类只是众多类中的一个;commons中有相当多的好类可以执行空安全操作
下面是一个示例,说明在包含apache库(commons-lang-2.4.jar)时如何在JAVA中使用null值
如果您使用的是Spring,Spring在其包中也有相同的功能,请参阅库(Spring-2.4.6.jar)
关于如何使用spring中的静态classf的示例(org.springframework.util.Assert)
如果不允许使用空值
如果在外部调用您的方法,请从以下内容开始:
public void method(Object object) {
if (object == null) {
throw new IllegalArgumentException("...");
}
if (object == null) {
// something
} else {
// something else
}
if ( "bar".equals(foo) ) {
// ...
}
static <T> T checkNotNull(T e) {
if (e == null) {
throw new NullPointerException();
}
return e;
}
public String getPostcode(Person person) {
return person?.getAddress()?.getPostcode();
}
@NotNull public static String helloWorld() {
return "Hello World";
}
ValidationUtils.getNullValidator().addParam(plans, "plans").addParam(persons, "persons").validate();
然后,在该方法的其余部分中,您将知道object
不是null
如果它是一个内部方法(不是API的一部分),只需记录它不能为null,就是这样
例如:
public String getFirst3Chars(String text) {
return text.subString(0, 3);
}
但是,如果您的方法只是传递值,而下一个方法传递值等等,则可能会出现问题。在这种情况下,您可能需要检查上述参数
如果允许null
这要看情况而定。如果发现我经常做这样的事情:
public void method(Object object) {
if (object == null) {
throw new IllegalArgumentException("...");
}
if (object == null) {
// something
} else {
// something else
}
if ( "bar".equals(foo) ) {
// ...
}
static <T> T checkNotNull(T e) {
if (e == null) {
throw new NullPointerException();
}
return e;
}
public String getPostcode(Person person) {
return person?.getAddress()?.getPostcode();
}
@NotNull public static String helloWorld() {
return "Hello World";
}
ValidationUtils.getNullValidator().addParam(plans, "plans").addParam(persons, "persons").validate();
所以我分支,做两件完全不同的事情。没有难看的代码片段,因为我确实需要根据数据做两件不同的事情。例如,我应该处理输入,还是应该计算一个好的默认值
实际上,我很少使用成语“if(object!=null&&…
”
如果你展示了你通常使用习惯用法的例子,那么给你举个例子可能会更容易。问这个问题表明你可能对错误处理策略感兴趣。如何以及在哪里处理错误是一个普遍存在的架构问题。有几种方法可以做到这一点
我的最爱:允许异常通过“主循环”或其他具有适当职责的函数捕获它们。检查错误条件并适当处理它们可以被视为一项专门的职责
当然也要看看面向方面的编程——如果(o==null)handleNull()插入if,它们有很好的方法
进入字节码。在我看来,这似乎是初级到中级开发人员在某一点上经常遇到的一个问题:他们要么不知道,要么不信任他们正在参与的合同,并且防御性地过度检查空值。此外,在编写自己的代码时,他们往往依赖于返回空值o表示这样要求调用方检查空值的内容
换句话说,有两种情况会出现空检查:
合同条款中的无效响应;以及
这不是一个有效的响应
(2) 很简单。可以使用assert
语句(断言)或允许失败(例如),断言是在1.4中添加的一个高度未充分使用的Java功能。语法为:
assert <condition>
解析器获取原始用户输入并查找要执行的操作,可能是在您为某个操作实现命令行界面的情况下。现在,您可能会签订合同,如果没有适当的操作,它将返回null。这导致了您所说的null检查
另一种解决方案是从不返回null,而是使用:
比较:
Parser parser = ParserFactory.getParser();
if (parser == null) {
// now what?
// this would be an example of where null isn't (or shouldn't be) a valid response
}
Action action = parser.findAction(someInput);
if (action == null) {
// do nothing
} else {
action.doSomething();
}
到
这是一个更好的设计,因为它可以产生更简洁的代码
也就是说,也许它完全适合findAction()方法引发带有有意义的错误消息的异常,尤其是在依赖用户输入的情况下。findAction方法引发异常比调用方法引发简单的NullPointerException而不进行解释要好得多
try {
ParserFactory.getParser().findAction(someInput).doSomething();
} catch(ActionNotFoundException anfe) {
userConsole.err(anfe.getMessage());
}
或者,如果您认为try/catch机制太难看,那么您的默认操作应该向用户提供反馈,而不是什么都不做
public Action findAction(final String userInput) {
/* Code to return requested Action if found */
return new Action() {
public void doSomething() {
userConsole.err("Action not found: " + userInput);
}
}
}
只有在这种情况下-
在调用equals方法之前不检查变量是否为null(下面是一个字符串比较示例):
如果foo
不存在,将导致NullPointerException
如果像这样比较字符串
s,可以避免这种情况:
public void method(Object object) {
if (object == null) {
throw new IllegalArgumentException("...");
}
if (object == null) {
// something
} else {
// something else
}
if ( "bar".equals(foo) ) {
// ...
}
static <T> T checkNotNull(T e) {
if (e == null) {
throw new NullPointerException();
}
return e;
}
public String getPostcode(Person person) {
return person?.getAddress()?.getPostcode();
}
@NotNull public static String helloWorld() {
return "Hello World";
}
ValidationUtils.getNullValidator().addParam(plans, "plans").addParam(persons, "persons").validate();
我尝试过NullObjectPattern
,但对我来说,这并不总是最好的方法。有时“不采取行动”并不合适
NullPointerException
是一个运行时异常,这意味着它是开发人员的错误,如果有足够的经验,它会告诉您错误的确切位置
现在回答:
尽量使所有属性及其访问器都是私有的,或者避免将它们暴露给客户端
iWantToDestroyEverything().something();
if (someobject == null) {
// Handle null here then move on.
}
if (someobject != null) {
.....
.....
.....
}
public static <T> T ifNull(T toCheck, T ifNull) {
if (toCheck == null) {
return ifNull;
}
return toCheck;
}
ValidationUtils.getNullValidator().addParam(plans, "plans").addParam(persons, "persons").validate();
void validate() throws ValidationException;
public Photo getPhotoOfThePerson(Person person) {
if (person == null)
return null;
// Grabbing some resources or intensive calculation
// using person object anyhow.
}
getPhotoOfThePerson(me.getGirlfriend())
getPhotoByName(me.getGirlfriend()?.getName())
public static MyEnum parseMyEnum(String value); // throws IllegalArgumentException
public static MyEnum parseMyEnumOrNull(String value);
/**
* @return photo or null
*/
/**
* @return photo, never null
*/
public Photo getGirlfriendPhoto() {
try {
return appContext.getPhotoDataSource().getPhotoByName(me.getGirlfriend().getName());
} catch (NullPointerException e) {
return null;
}
}
public SomeValue calculateSomeValueUsingSophisticatedLogic(Predicate predicate) {
try {
Result1 result1 = performSomeCalculation(predicate);
Result2 result2 = performSomeOtherCalculation(result1.getSomeProperty());
Result3 result3 = performThirdCalculation(result2.getSomeProperty());
Result4 result4 = performLastCalculation(result3.getSomeProperty());
return result4.getSomeProperty();
} catch (NullPointerException e) {
return null;
}
}
public SomeValue calculateSomeValueUsingSophisticatedLogic(Predicate predicate) {
SomeValue result = null;
if (predicate != null) {
Result1 result1 = performSomeCalculation(predicate);
if (result1 != null && result1.getSomeProperty() != null) {
Result2 result2 = performSomeOtherCalculation(result1.getSomeProperty());
if (result2 != null && result2.getSomeProperty() != null) {
Result3 result3 = performThirdCalculation(result2.getSomeProperty());
if (result3 != null && result3.getSomeProperty() != null) {
Result4 result4 = performLastCalculation(result3.getSomeProperty());
if (result4 != null) {
result = result4.getSomeProperty();
}
}
}
}
}
return result;
}
public void updatePersonPhoneNumber(Long personId, String phoneNumber) {
if (personId == null)
return;
DataSource dataSource = appContext.getStuffDataSource();
Person person = dataSource.getPersonById(personId);
if (person != null) {
person.setPhoneNumber(phoneNumber);
dataSource.updatePerson(person);
} else {
Person = new Person(personId);
person.setPhoneNumber(phoneNumber);
dataSource.insertPerson(person);
}
}
public void updatePersonPhoneNumber(Long personId, String phoneNumber) {
if (personId == null)
return;
DataSource dataSource = appContext.getStuffDataSource();
Person person = dataSource.getPersonById(personId);
if (person == null)
throw new SomeReasonableUserException("What are you thinking about ???");
person.setPhoneNumber(phoneNumber);
dataSource.updatePerson(person);
}
Optional<Integer> possible = Optional.of(5);
possible.isPresent(); // returns true
possible.get(); // returns 5
Objects.requireNonNull(someObject);
someObject.doCalc();
Parent(Child child) {
if (child == null) {
throw new NullPointerException("child");
}
this.child = child;
}
Parent(Child child) {
this.child = Objects.requireNonNull(child, "child");
}
class C {
private final MyType mustBeSet;
public C(MyType mything) {
mustBeSet=Contract.notNull(mything);
}
private String name = "<unknown>";
public void setName(String s) {
name = Contract.notNull(s);
}
}
class Contract {
public static <T> T notNull(T t) { if (t == null) { throw new ContractException("argument must be non-null"); return t; }
}
public static Optional<Fruit> find(String name, List<Fruit> fruits) {
for (Fruit fruit : fruits) {
if (fruit.getName().equals(name)) {
return Optional.of(fruit);
}
}
return Optional.empty();
}
Optional<Fruit> found = find("lemon", fruits);
if (found.isPresent()) {
Fruit fruit = found.get();
String name = fruit.getName();
}
String nameOrNull = find("lemon", fruits)
.map(f -> f.getName())
.orElse("empty-name");
// Bad
ArrayList<String> lemmings;
String[] names;
void checkLemmings() {
if (lemmings != null) for(lemming: lemmings) {
// do something
}
}
// Good
ArrayList<String> lemmings = new ArrayList<String>();
String[] names = {};
void checkLemmings() {
for(lemming: lemmings) {
// do something
}
}
if(object == null){
//you called my method badly!
if(str.length() == 0){
//you called my method badly again!
}
getCustomerAccounts(@NotEmpty String customerId,@Size(min = 1) String accountType)
public class Car {
@NotNull
private String manufacturer;
@NotNull
@Size(min = 2, max = 14)
private String licensePlate;
@Min(2)
private int seatCount;
// ...
}
org.apache.commons.lang.Validate //using apache framework
if(someObject!=null){ // simply checking against null
}
@isNull @Nullable // using annotation based validation
// by writing static method and calling it across whereever we needed to check the validation
static <T> T isNull(someObject e){
if(e == null){
throw new NullPointerException();
}
return e;
}
public Optional<Service> getRefrigertorControl() {
Service s = new RefrigeratorService();
//...
return Optional.ofNullable(s);
}
Optional ref = homeServices.getRefrigertorControl();
ref.ifPresent(HomeServices::switchItOn);
@FunctionalInterface
public interface Consumer<T>
public static Optional<HomeServices> get() {
service = Optional.of(service.orElse(new HomeServices()));
return service;
}
import java.util.Optional;
public class HomeServices {
private static final int NOW = 0;
private static Optional<HomeServices> service;
public static Optional<HomeServices> get() {
service = Optional.of(service.orElse(new HomeServices()));
return service;
}
public Optional<Service> getRefrigertorControl() {
Service s = new RefrigeratorService();
//...
return Optional.ofNullable(s);
}
public static void main(String[] args) {
/* Get Home Services handle */
Optional<HomeServices> homeServices = HomeServices.get();
if(homeServices != null) {
Optional<Service> refrigertorControl = homeServices.get().getRefrigertorControl();
refrigertorControl.ifPresent(HomeServices::switchItOn);
}
}
public static void switchItOn(Service s){
//...
}
}
Optional stringToUse = Optional.of("optional is there");
stringToUse.ifPresent(System.out::println);
Optional<Integer> i = Optional.ofNullable(wsObject.getFoo())
.map(f -> f.getBar())
.map(b -> b.getBaz())
.map(b -> b.getInt());
Optional optionalCarNull = Optional.ofNullable(someNull);
optionalCarNull.orElseThrow(IllegalStateException::new);
String lowerVal = Objects.requireNonNull(someVar, "input cannot be null or empty").toLowerCase();