Новый класс Optional в Java 8, не панацея от NullPointerException

от автора

В релизе Java 8 появился новый класс Optional призванный помочь разработчикам в обработке NullPointerException.

С NullPointerException встречались многие и во многих случаях, это очень неприятное исключение заставляет дебажить код, дабы понять, в каком месте, кто-то из твоих предшественников(а возможно и ты), не поставили пресловутую проверку на null.

А что если вообще запретить назначать тем или иным полям класса значения равные null? Java естественно не запрещает нам делать этого, но с Optional это становится немного удобнее и нагляднее.

Итак, приступим к описанию основных возможностей этого нововведения.

Создание объектов Optional

Для начала приведу пример класса с использованием Optional:

import java.util.Date; import java.util.Optional;  public class Person {  	private Optional<String> firstName; 	 	private Optional<String> secondName; 	 	private Optional<Integer> age; 	 	private Optional<PersonAddress> address; 	 	public Optional<String> getFirstName() { 		return firstName; 	}  	public void setFirstName(String firstName) { 		this.firstName = Optional.ofNullable(firstName); 	}  	public Optional<String> getSecondName() { 		return secondName; 	}  	public void setSecondName(String secondName) { 		this.secondName = Optional.of(secondName); 	}  	public Optional<Integer> getAge() { 		return age; 	}  	public void setAge(int age) { 		this.age = Optional.ofNullable(age); 	} 	 	public Optional<PersonAddress> getAddress() { 		return address; 	}  	public void setAddress(PersonAddress address) { 		this.address = Optional.of(address); 	} } 

Как видите при установке полям класса значений, через «set» методы, мы используем статические методы класса Optional - of(), ofNullable()).

Эти методы используются для создания объектов типа Optional, ниже приведены примеры такого создания объектов:

/** Создание Optional объектов */ 		 //Пустой Optional объект Optional<Person> optionalPerson = Optional.empty(); 	 //Optional объект с ненулевым значением Optional<Person> optionalNonNull = Optional.of(new Person()); 		 //Optional объект с возможностью нулевого значения Optional<Person> optionalNullable = Optional.ofNullable(new Person()); 

Использование Optional для устранения избыточного кода

Часто проверка на null объектов, которые передаются или обрабатываются в различных методах, занимает множество строчек кода, если необходимо работать не только с переданным объектом, а с полем объекта, которое в свою очередь содержит еще одно поле, к примеру текстового описания.

При попытке обратиться напрямую к этому полю через цепочку объектов и при условии, что переданный объект по каким-то причинам пришел равный null мы получим NullPointerException, поэтому для начала нам необходимо проверить каждый объект на null и уже потом взять необходимое нам текстовое поле:

Person person = getDefaultPerson(); 	if (person != null) { 		PersonAddress personAddress = person.getAddress(); 			if (personAddress != null) { 				PersonAddressStreet street = personAddress.getStreet(); 				if(street != null) { 					streetName = street.getStreetName(); 				} else { 					streetName = "EMPTY"; 				} 			} 	} 

А теперь все то же самое, но с использованием Optional:

String streetName = person.flatMap(Person::getAddress)                .flatMap(PersonAddress::getStreet)                .map(PersonAddressStreet::getStreetName)                .orElse("EMPTY"); 

Намного лаконичнее, не правда ли?

Действия с объектом, с использованием метода ifPresent()

Метод ifPresent() позволяет также устранить некоторую избыточность кода, следующего вида:

 if(person != null) { 	System.out.println(person);  } 

Те же действия, но с использованием Optional:

person.ifPresent(System.out::println); 

Действия с объектом с использованием isPresent()

isPresent() не дает нам большой выгоды по устранению избыточности кода, но зато придает немного большую информативность написанному коду.

Как было раньше:

if(person != null) { 	System.out.println(person) } else { 	System.out.println("Person not found!");  } 

То же самое, но с использованием Optional:

if (person.isPresent()) { 	System.out.println(person.get()); } else { 	System.out.println("Person not found!"); } 

Действия с объектом с использованием orElse(), orElseThrow()

И напоследок еще несколько методов для наведения «красоты» в коде.

Как было раньше:

Person personNew = person != null ? person : new Person(); 

То же самое, но с использованием Optional:

Person personNew = person.orElse(new Person()); 

Или, если не хотим создавать объект, можно выбросить исключение:

Person personNewThrow = person.orElseThrow(Exception::new); 

Заключение

Естественно Optional не дает никакой гарантии избавления от NullPointerException и все проверки на null можно было описывать и раньше, но с Optional это действия становятся быстрее и проще, так как дополнительные методы для проверки объекта или проверки и каких-то дальнейших действий с объектом уже описаны и нам осталось только воспользоваться ими в своем коде.

А также несомненно, Optional помогает придать большую информативность коду, повысить его читабельность.

На этом я завершу, свое короткое описания данного нововведения, спасибо за прочтение! Дополнительную информацию по этой теме Вы сможете найти по ссылкам, приведенным ниже.

Информация для дальнейшего изучения:

ссылка на оригинал статьи http://habrahabr.ru/post/225641/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *