1. 程式人生 > 其它 >vscode 使用者程式碼片段

vscode 使用者程式碼片段

大量判空的程式碼

實際中,物件不判空會導致空指標異常。

為了規避為指標,不得不寫出這種非常冗長又醜陋的空指標判斷。

public void tooMuchNull(Worker worker) {
	if (worker != null) {
		Address address=worker.getAddress();
		if (address != null) {
			String city=address.getCity();
		}
	}
}

Optional<T>

Optional<T>包含的物件value可能非null,也可能為null。

常建的構建Optional<T>物件的方法,有ofNullable(T value)、of(T value)。

構建時,最終都會呼叫Optional的構造方法Optional(T value)。

而常見的判斷Optional結果的方法有,orElse()、ifPresent()、get()、empty()、map()、flatMap()。

api圖

如下圖所示:

程式碼示例:

  • orElse():
/**
 * orElse(預設值),如果Optional<T>封裝的物件不存在值,則返回預設值。
 */
public void orElseDemo() {
//		Worker worker1=new Worker("123",18,"lin");
	Worker worker1 = null
; Worker worker2 = new Worker("456", 28, "chen"); //如果worker1不為null,則orElse返回worker1,否則返回預設值worker2 Worker result = Optional.ofNullable(worker1).orElse(worker2); //相當於以下程式碼: // if (worker1 != null) { // result = worker1; // } else { // result = worker2; // } System.out.println(result.getName() + "," + result.getAge()); }
  • orElseGet():
/**
 * orElseGet(),如果Optional<T>封裝的物件不存在值,則執行Supplier函式式。
 * orElseGet(Supplier<? extends T> other),返回的型別必須和Optional封裝的物件型別一致。
 */
public void ofElseGetDemo() {
	String name1 = null;
	String name2 = "lin";
	//orElseGet(Supplier<? extends T> other),返回的型別必須和Optional封裝的物件型別一致。
        String result = Optional.ofNullable(name1).orElseGet(()-> name2+"def");
	System.out.println(result);
}

  • of():
/**
 * of(物件),如果封裝的物件為空,則會報出空指標異常
 */
public void ofDemo() {
//		Worker worker1=new Worker("123",18,"lin");
	Worker worker1 = null;
	Worker worker2 = new Worker("456", 28, "chen");
	Worker result = Optional.of(worker1).orElse(worker2);
	System.out.println(result.getName() + "," + result.getAge());
}
  • isPresent():
/**
 * isPresent()表示如果Optional<T>封裝的物件不為空,就返回true。
 */
public void isPresentDemo() {
	Worker worker1 = new Worker("123", 18, "lin");
	Optional<Worker> workerOpt = Optional.ofNullable(worker1);
	//這種寫法比較醜,可以直接用下面的ifPresent()方法代替。
	boolean isPresent = workerOpt.isPresent();
	if (isPresent) {
		System.out.println(workerOpt.get().getName());
	}
	//以上程式碼,相當於:
//		if (worker1 != null) {
//			System.out.println(worker1.getName());
//		}
}
  • ifPresent(lambda):
/**
 * ifPresent(lambda)表示如果物件不為null,則會執行對應的lambda語句。
 */
public void ifPresentDemo() {
//		Address address=new Address("中國","廣東","深圳");
//		Worker worker1=new Worker("123",18,"lin",address);
	Worker worker1 = new Worker("123", 18, "lin");
//		Worker worker1=null;
	List<String> nameList = new ArrayList<>();
	Optional.ofNullable(worker1).ifPresent(worker -> nameList.add(worker.getName()));
	//上面這句程式碼的作用相當於以下注釋的程式碼:
//		if (worker1 != null) {
//			nameList.add(worker1.getName());
//		}
	nameList.forEach(System.out::println);
}

  • map(lambda):

map的引數裡面是lambda表示式,會從Optional物件中進行對映,提取和轉換值。
map是一個非常實用的方法。用得也比較多。
比如:

String name = "";
if (person!=null) {
    name = person.getName();
}

這種大量的判空在專案開發中隨處可見。可以使用 Optional的 map方法替換。

String name = Optional.ofNullable(person).map(Person::getName).orElse("");

其他示例:

public  void mapDemo() {
    String str=" test ";
    Optional.ofNullable(str).map(String::trim)
	.filter(t -> t.length()> 1)
	.ifPresent(s->{
	    s+="1234";
	    System.out.println(s);
	});
//相當於以下程式碼:
//	if (str != null) {
//	    str=str.trim();
//	    if (str.length() > 1) {
//		str+="1234";
//		System.out.println(str);
//	    }
//	}
}
  • flatMap(lambda):

flatMap()的引數是lambda表示式,返回值是Optional。

/**
 * flatMap(),如果Optional封裝物件不為空,就會執行對應的mapping函式,返回Optional型別的值,否則就返回一個空的Optional物件。
 * 通過flatMap(),可以不斷地返回Optional物件,一直進行鏈式呼叫。非常重要~
 */
public void flatMapDemo() {
	Address address = new Address("中國", "廣東", "深圳");
	Worker worker = new Worker("123", 18, "lin", address);
	String city = Optional.ofNullable(worker)
			.flatMap(Worker::getAdress)
			.flatMap(Address::getCity)
			.orElse("default");
	System.out.println(city);
}
  • orElseThrow():
/**
 * orElseThrow(),如果Optional封裝的物件為空,就會丟擲對應的異常。
 */
public void orElseThrowDemo() {
//		Worker worker = new Worker("123", 18, "lin");
	Worker worker = null;
	Worker result = Optional.ofNullable(worker)
			.orElseThrow(IllegalArgumentException::new);
	System.out.println(result.getName());
}
  • filter(lambda):
public void filterDemo() {
	Worker worker = new Worker("123", 18, "lin");
	Optional<Worker> result = Optional.ofNullable(worker)
			.filter(worker1 -> worker1.getAge() > 20);
	//如果符合條件(比如,年齡大於20)則為true,不符合則為false
	System.out.println(result.isPresent());
}

區別:

  • of() 和 ofNullable() 的區別:

這兩個方法都可以建立包含值的 Optional。
不同之處在於如果你把 null值作為引數傳遞進ofNullable(),而傳遞null作為引數時,of() 方法會丟擲 NullPointerException。

  • orElse()和orElseGet()的區別:
    orElse(預設值),表示如果有值則返回該值,否則返回傳遞給它的預設值。

orElseGet(lambda表示式)會在有值的時候返回值,如果沒有值,它會執行作為引數傳入的函式式介面(返回型別必須和Optional封裝的物件是同一種類型),並將返回其執行結果。

需要特別注意的是:

Optional的orElse()若方法不是純計算型的,有與資料庫互動或者遠端呼叫的,都應該使用orElseGet() 。

orElse()無論前面Optional容器是null還是non-null,都會執行orElse裡的方法,orElseGet()並不會。

詳情參見:https://blog.csdn.net/weixin_30437337/article/details/95443798

  • isPresent()和ifPresent(lambda)的區別:

看方法名is開頭,就可以知道isPresent()返回的是布林值。而ifPresent()則是如果對應的值存在,就會執行函式式介面。

  • flatMap(lambda)和map(lambda)的區別:

值不為空時,兩者都會執行引數中的函式式介面。

而flatMap()返回值是Optional,通過不斷地產生Optional,可以進行鏈式呼叫。

可以重構的示例:

回頭看一下開頭的程式碼,如下:

public void tooMuchNull(Worker worker) {
	if (worker != null) {
		Address address=worker.getAddress();
		if (address != null) {
			String city=address.getCity();
		}
	}
}

下面嘗試用Optional改寫。

重寫getter()

重寫getter,返回Optional物件。

public class User {
    private Address address;

    public Optional<Address> getAddress() {
        return Optional.ofNullable(address);
    }

    // ...
}

優化

重寫完getter後,上面的例子,可以用Optional改寫為:

public void preventNullPointer() {
    Worker worker = new Worker("123", 18, "lin");

    String result = Optional.ofNullable(worker)
      .flatMap(u -> u.getAddress())
      .flatMap(a -> a.getCity())
      .orElse("default");

}

再進一步簡寫成:

String city = Optional.ofNullable(worker)
		.flatMap(Worker::getAdress)
		.flatMap(Address::getCity)
		.orElse("default");

使用Optional要注意:

  • Optional 主要用作返回型別。

  • Optional不能作為入參的引數.

  • Optional不會序列化,不要直接作為物件屬性。

  • Optional不要用於集合操作。空集合請使用Collections.emptyList()。

程式碼地址:

https://github.com/firefoxer1992/JavaDemo/tree/master/src/main/java/com/java8

參考資料:

https://www.cnblogs.com/zhangboyu/p/7580262.html

https://juejin.im/post/5e66ecdc518825490d126a16

大量判空的程式碼

實際中,物件不判空會導致空指標異常。

為了規避為指標,不得不寫出這種非常冗長又醜陋的空指標判斷。

public void tooMuchNull(Worker worker) {
	if (worker != null) {
		Address address=worker.getAddress();
		if (address != null) {
			String city=address.getCity();
		}
	}
}

Optional<T>

Optional<T>包含的物件value可能非null,也可能為null。

常建的構建Optional<T>物件的方法,有ofNullable(T value)、of(T value)。

構建時,最終都會呼叫Optional的構造方法Optional(T value)。

而常見的判斷Optional結果的方法有,orElse()、ifPresent()、get()、empty()、map()、flatMap()。

api圖

如下圖所示:

程式碼示例:

  • orElse():
/**
 * orElse(預設值),如果Optional<T>封裝的物件不存在值,則返回預設值。
 */
public void orElseDemo() {
//		Worker worker1=new Worker("123",18,"lin");
	Worker worker1 = null;
	Worker worker2 = new Worker("456", 28, "chen");
	//如果worker1不為null,則orElse返回worker1,否則返回預設值worker2
	Worker result = Optional.ofNullable(worker1).orElse(worker2);

	//相當於以下程式碼:
//		if (worker1 != null) {
//			result = worker1;
//		} else {
//			result = worker2;
//		}
	System.out.println(result.getName() + "," + result.getAge());
}
  • orElseGet():
/**
 * orElseGet(),如果Optional<T>封裝的物件不存在值,則執行Supplier函式式。
 * orElseGet(Supplier<? extends T> other),返回的型別必須和Optional封裝的物件型別一致。
 */
public void ofElseGetDemo() {
	String name1 = null;
	String name2 = "lin";
	//orElseGet(Supplier<? extends T> other),返回的型別必須和Optional封裝的物件型別一致。
        String result = Optional.ofNullable(name1).orElseGet(()-> name2+"def");
	System.out.println(result);
}

  • of():
/**
 * of(物件),如果封裝的物件為空,則會報出空指標異常
 */
public void ofDemo() {
//		Worker worker1=new Worker("123",18,"lin");
	Worker worker1 = null;
	Worker worker2 = new Worker("456", 28, "chen");
	Worker result = Optional.of(worker1).orElse(worker2);
	System.out.println(result.getName() + "," + result.getAge());
}
  • isPresent():
/**
 * isPresent()表示如果Optional<T>封裝的物件不為空,就返回true。
 */
public void isPresentDemo() {
	Worker worker1 = new Worker("123", 18, "lin");
	Optional<Worker> workerOpt = Optional.ofNullable(worker1);
	//這種寫法比較醜,可以直接用下面的ifPresent()方法代替。
	boolean isPresent = workerOpt.isPresent();
	if (isPresent) {
		System.out.println(workerOpt.get().getName());
	}
	//以上程式碼,相當於:
//		if (worker1 != null) {
//			System.out.println(worker1.getName());
//		}
}
  • ifPresent(lambda):
/**
 * ifPresent(lambda)表示如果物件不為null,則會執行對應的lambda語句。
 */
public void ifPresentDemo() {
//		Address address=new Address("中國","廣東","深圳");
//		Worker worker1=new Worker("123",18,"lin",address);
	Worker worker1 = new Worker("123", 18, "lin");
//		Worker worker1=null;
	List<String> nameList = new ArrayList<>();
	Optional.ofNullable(worker1).ifPresent(worker -> nameList.add(worker.getName()));
	//上面這句程式碼的作用相當於以下注釋的程式碼:
//		if (worker1 != null) {
//			nameList.add(worker1.getName());
//		}
	nameList.forEach(System.out::println);
}

  • map(lambda):

map的引數裡面是lambda表示式,會從Optional物件中進行對映,提取和轉換值。
map是一個非常實用的方法。用得也比較多。
比如:

String name = "";
if (person!=null) {
    name = person.getName();
}

這種大量的判空在專案開發中隨處可見。可以使用 Optional的 map方法替換。

String name = Optional.ofNullable(person).map(Person::getName).orElse("");

其他示例:

public  void mapDemo() {
    String str=" test ";
    Optional.ofNullable(str).map(String::trim)
	.filter(t -> t.length()> 1)
	.ifPresent(s->{
	    s+="1234";
	    System.out.println(s);
	});
//相當於以下程式碼:
//	if (str != null) {
//	    str=str.trim();
//	    if (str.length() > 1) {
//		str+="1234";
//		System.out.println(str);
//	    }
//	}
}
  • flatMap(lambda):

flatMap()的引數是lambda表示式,返回值是Optional。

/**
 * flatMap(),如果Optional封裝物件不為空,就會執行對應的mapping函式,返回Optional型別的值,否則就返回一個空的Optional物件。
 * 通過flatMap(),可以不斷地返回Optional物件,一直進行鏈式呼叫。非常重要~
 */
public void flatMapDemo() {
	Address address = new Address("中國", "廣東", "深圳");
	Worker worker = new Worker("123", 18, "lin", address);
	String city = Optional.ofNullable(worker)
			.flatMap(Worker::getAdress)
			.flatMap(Address::getCity)
			.orElse("default");
	System.out.println(city);
}
  • orElseThrow():
/**
 * orElseThrow(),如果Optional封裝的物件為空,就會丟擲對應的異常。
 */
public void orElseThrowDemo() {
//		Worker worker = new Worker("123", 18, "lin");
	Worker worker = null;
	Worker result = Optional.ofNullable(worker)
			.orElseThrow(IllegalArgumentException::new);
	System.out.println(result.getName());
}
  • filter(lambda):
public void filterDemo() {
	Worker worker = new Worker("123", 18, "lin");
	Optional<Worker> result = Optional.ofNullable(worker)
			.filter(worker1 -> worker1.getAge() > 20);
	//如果符合條件(比如,年齡大於20)則為true,不符合則為false
	System.out.println(result.isPresent());
}

區別:

  • of() 和 ofNullable() 的區別:

這兩個方法都可以建立包含值的 Optional。
不同之處在於如果你把 null值作為引數傳遞進ofNullable(),而傳遞null作為引數時,of() 方法會丟擲 NullPointerException。

  • orElse()和orElseGet()的區別:
    orElse(預設值),表示如果有值則返回該值,否則返回傳遞給它的預設值。

orElseGet(lambda表示式)會在有值的時候返回值,如果沒有值,它會執行作為引數傳入的函式式介面(返回型別必須和Optional封裝的物件是同一種類型),並將返回其執行結果。

需要特別注意的是:

Optional的orElse()若方法不是純計算型的,有與資料庫互動或者遠端呼叫的,都應該使用orElseGet() 。

orElse()無論前面Optional容器是null還是non-null,都會執行orElse裡的方法,orElseGet()並不會。

詳情參見:https://blog.csdn.net/weixin_30437337/article/details/95443798

  • isPresent()和ifPresent(lambda)的區別:

看方法名is開頭,就可以知道isPresent()返回的是布林值。而ifPresent()則是如果對應的值存在,就會執行函式式介面。

  • flatMap(lambda)和map(lambda)的區別:

值不為空時,兩者都會執行引數中的函式式介面。

而flatMap()返回值是Optional,通過不斷地產生Optional,可以進行鏈式呼叫。

可以重構的示例:

回頭看一下開頭的程式碼,如下:

public void tooMuchNull(Worker worker) {
	if (worker != null) {
		Address address=worker.getAddress();
		if (address != null) {
			String city=address.getCity();
		}
	}
}

下面嘗試用Optional改寫。

重寫getter()

重寫getter,返回Optional物件。

public class User {
    private Address address;

    public Optional<Address> getAddress() {
        return Optional.ofNullable(address);
    }

    // ...
}

優化

重寫完getter後,上面的例子,可以用Optional改寫為:

public void preventNullPointer() {
    Worker worker = new Worker("123", 18, "lin");

    String result = Optional.ofNullable(worker)
      .flatMap(u -> u.getAddress())
      .flatMap(a -> a.getCity())
      .orElse("default");

}

再進一步簡寫成:

String city = Optional.ofNullable(worker)
		.flatMap(Worker::getAdress)
		.flatMap(Address::getCity)
		.orElse("default");

使用Optional要注意:

  • Optional 主要用作返回型別。

  • Optional不能作為入參的引數.

  • Optional不會序列化,不要直接作為物件屬性。

  • Optional不要用於集合操作。空集合請使用Collections.emptyList()。

程式碼地址:

https://github.com/firefoxer1992/JavaDemo/tree/master/src/main/java/com/java8

參考資料:

https://www.cnblogs.com/zhangboyu/p/7580262.html

https://juejin.im/post/5e66ecdc518825490d126a16