Java 8的Optional避免空指針錯誤

Java 8的Optional避免空指針錯誤


忘記檢查空值引用是應用代碼中一類常見的bug來源。消除NullPointerExceptions的方式之一是確保方法總是返回一個非空值。例如如下方法:

public interface CustomerRepository extends CrudRepository

{

/**

* returns the customer for the specified id or

* null if the value is not found

*/

public Customer findCustomerById(String id);

}

用如下有缺陷的代碼來調用CustomerRepository :

Customer customer = customerRepository.findCustomerById(“123”);

customer.getName(); // 得到空指針錯誤

這段代碼的正確寫法應該是:

Customer customer = customerRepository.findCustomerById(“123”);if(customer != null) {

customer.getName(); // 避免空指針錯誤

}

理想狀態下,如果我們沒有檢查某個值能否為空,我們希望編譯器及時發現。java.util.Optional類讓我們可以像這樣寫接口:

public interface CustomerRepository extends CrudRepository {

public Optional findCustomerById(String id);}

這樣一來,這段代碼的有缺陷版本不會被編譯,開發者必須顯式地檢查這個Optional類型對象是否有值,代碼如下:

Optional optional = customerRepository.findCustomerById(“123”);

if(optional.isPresent()) {

Customer customer = optional.get();

customer.getName();

}

所以Optional的關鍵點在於確保開發者不用查閱Javadoc就能知道某個方法可以返回null,或者可以把一個null值傳給某方法。編譯器和方法簽名有助於開發者明確知道某個值是Optional類型。關於Optional類思想的詳細描述請參考這裡。

Spring 4.1有兩種方式支持Java Optional。Spring的@Autowired註解有一個屬性"required",使用之後我們可以把如下代碼:

@Service

public class MyService {

@Autowired(required=false)

OtherService otherService;

public doSomething() {

if(otherService != null) {

// use other service

}

}}

替換成:

public class MyService {

@Autowired

Optional otherService;

public doSomething() {

otherService.ifPresent( s -> {

// use s to do something

});

}}

另一個能用Optional的地方是Spring MVC框架,可以用於表示某個處理方法的參數是可選的。例如:

@RequestMapping(“/accounts/{accountId}”,requestMethod=RequestMethod.POST)

void update(Optional accountId, @RequestBody Account account)

這段代碼會告訴Spring其accountId是可選參數。

總之,Java 8的Optional類通過減少空指針錯誤相關的缺陷簡化了代碼編寫,同時Spring能很好地支持Java 8的Optional類。


分享到:


相關文章: