面試官寫了個雙冒號::問我是什麼語法,Java中有這玩意麼?

千鋒Python唐小強發表於2020-08-07

一:簡潔

方法引用分為三種,方法引用透過一對雙冒號:: 來表示,方法引用是一種函式式介面的另一種書寫方式

  • 靜態方法引用,透過類名::靜態方法名, 如 Integer::parseInt
  • 例項方法引用,透過例項物件::例項方法,如 str::substring
  • 構造方法引用,透過類名::new, 如 User::new

二:方法引用


public 
final 

class 
Integer {

    public static int parseInt (String s) throws NumberFormatException {
        return parseInt(s, 10);
   }
}
面試官寫了個雙冒號::問我是什麼語法,Java中有這玩意麼?

透過方法引用,可以將方法的引用賦值給一個變數,透過賦值給Function,說明方法引用也是一種函式式介面的書寫方式,Lambda表示式也是一種函式式介面,Lambda表示式一般用於自己提供方法體,而方法引用一般直接引用現成的方法。


public 

class 
User {

    private String username;
    private Integer age;

    public User () {
   }

    public User (String username, Integer age) {
        this.username = username;
        this.age = age;
   }

    @Override
    public String toString () {
        return "User{" +
                "username='" + username + '\'' +
                ", age=" + age +
                '}';
   }

    // Getter&Setter
}
public static void main(String[] args) {
   // 使用雙冒號::來構造靜態函式引用
   Function<String, Integer> fun = Integer::parseInt;
   Integer value = fun.apply("123");
   System.out.println(value);

   // 使用雙冒號::來構造非靜態函式引用
   String content = "Hello JDK8";
   Function<Integer, String> func = content::substring;
   String result = func.apply(1);
   System.out.println(result);

   // 建構函式引用
   BiFunction<String, Integer, User> biFunction = User::new;
   User user = biFunction.apply("mengday", 28);
   System.out.println(user.toString());

   // 函式引用也是一種函式式介面,所以也可以將函式引用作為方法的引數
   sayHello(String::toUpperCase, "hello");
}

// 方法有兩個引數,一個是
private static void sayHello(Function<String, String> func, String parameter){
   String result = func.apply(parameter);
   System.out.println(result);
}

三:Optional 可選值

在Google Guava 中就有Optional,在Swift語言中也有這樣類似的語法,在Swift中將可選值作為一種資料型別,地位和基本型別平齊平做,地位非常高。

package java.util;


import java.util . function. Consumer;
import java.util . function. Function;
import java.util . function. Predicate;
import java.util . function. Supplier;

/**
* @since 1.8
*/
public final class Optional< T> {
    private static final Optional <?> EMPTY = new Optional<>();

    private final T value;

    private Optional() {
       this.value = null;
   }

    // 返回一個空的 Optional例項
   public static<T> Optional<T> empty() {
       @SuppressWarnings("unchecked")
       Optional<T> t = (Optional<T>) EMPTY;
       return t;
   }

   private Optional(T value) {
       this.value = Objects.requireNonNull(value);
   }

   // 返回具有 Optional的當前非空值的Optional
   public static <T> Optional<T> of(T value) {
       return new Optional<>(value);
   }

   // 返回一個 Optional指定值的Optional,如果非空,則返回一個空的 Optional
   public static <T> Optional<T> ofNullable(T value) {
       return value == null ? empty() : of(value);
   }

   // 如果Optional中有一個值,返回值,否則丟擲 NoSuchElementException 。
   public T get() {
       if (value == null) {
           throw new NoSuchElementException("No value present");
       }
       return value;
   }

   // 返回true如果存在值,否則為 false
   public boolean isPresent() {
       return value != null;
   }

   // 如果存在值,則使用該值呼叫指定的消費者,否則不執行任何操作。
   public void ifPresent(Consumer <? super T> consumer) {
       if (value != null)
           consumer.accept(value);
   }

   // 如果一個值存在,並且該值給定的謂詞相匹配時,返回一個 Optional描述的值,否則返回一個空的 Optional
   public Optional<T> filter(Predicate <? super T> predicate) {
       Objects.requireNonNull(predicate);
       if (!isPresent())
           return this;
       else
           return predicate.test(value) ? this : empty();
   }

   // 如果存在一個值,則應用提供的對映函式,如果結果不為空,則返回一個 Optional結果的 Optional 。
   public<U> Optional<U> map(Function <? super T, ? extends U> mapper) {
       Objects.requireNonNull(mapper);
       if (!isPresent())
           return empty();
       else {
           return Optional.ofNullable(mapper.apply(value));
       }
   }

   // 如果一個值存在,應用提供的 Optional對映函式給它,返回該結果,否則返回一個空的 Optional 。
   public<U> Optional<U> flatMap(Function <? super T, Optional<U>> mapper) {
       Objects.requireNonNull(mapper);
       if (!isPresent())
           return empty();
       else {
           return Objects.requireNonNull(mapper.apply(value));
       }
   }

   // 如果值存在,就返回值,不存在就返回指定的其他值
   public T orElse(T other) {
       return value != null ? value : other;
   }


   public T orElseGet(Supplier <? extends T> other) {
       return value != null ? value : other.get();
   }

   public <X extends Throwable> T orElseThrow(Supplier <? extends X> exceptionSupplier) throws X {
       if (value != null) {
           return value;
       } else {
           throw exceptionSupplier.get();
       }
   }
}

關於of方法,現在好像很流行,就是提供一個static方法,方法名稱叫of,方法的返回值返回當前類,並且把建構函式設定為私有private,用靜態of方法來代替建構函式。


public 

class 
User {

    private String username;
    private Integer age;

    private User () {
   }

    public static User of () {
        return new User();
   }

    private User (String username, Integer age) {
        this.username = username;
        this.age = age;
   }

    public static User of (String username, Integer age) {
        return new User(username, age);
   }
}
Main
public static void main (String[] args) {
    // Optional類已經成為Java 8類庫的一部分,在Guava中早就有了,可能Oracle是直接拿來使用了
   // Optional用來解決空指標異常,使程式碼更加嚴謹,防止因為空指標NullPointerException對程式碼造成影響
   String msg = "hello";
   Optional<String> optional = Optional.of(msg);
   // 判斷是否有值,不為空
   boolean present = optional.isPresent();
   // 如果有值,則返回值,如果等於空則拋異常
   String value = optional.get();
   // 如果為空,返回else指定的值
   String hi = optional.orElse("hi");
   // 如果值不為空,就執行Lambda表示式
   optional.ifPresent(opt -> System.out.println(opt));
}


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69923331/viewspace-2710085/,如需轉載,請註明出處,否則將追究法律責任。

相關文章