避免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();