Java中基於泛型的交叉型別 - {4Comprehension}

banq發表於2019-07-09

簡單地說,交集型別是通過組合至少兩種不同型別而建立的匿名型別的形式。

想象一下,我們需要模擬兩種型別的動物:

  • 那些可以飛的
  • 那些可以游泳的

我們可以簡單地實現兩個介面:

class SailfinFlyingfish implements Swimmable, Flyable {

    @Override
    public void fly() {
        System.out.println("*flap flap*");
    }

    @Override
    public void swim() {
        System.out.println("*swim swim*");
    }
}

但是,如果我們想要建立一種只接受可以游泳和飛行的動物的方法呢?

public static void process(... animal) { 
    animal.fly();
    animal.swim();
}

變通方式是引入合成介面:

interface FlyableAndSwimmable extends Flyable, Swimmable { }

但這涉及相當多額外的樣板程式碼,也不是很有彈性,但至少是型別安全的。

基於泛型的交叉型別(intersection type

我們可以在定義泛型型別變數時使用該語法:

public static <T extends Flyable & Swimmable> void process(T animal) {
    animal.fly();
    animal.swim();
}

Java語言規範:

交叉型別採用T1&...&Tn(n> 0)的形式,其中Ti(1≤i≤n)是型別。

An intersection type takes the form T1 & … & Tn (n > 0), where Ti (1 ≤ i ≤ n) are types.

它可能看起來像一個基於泛型的黑客,但它實際上是一個完全成熟的合法Java功能 - 只是以一種有趣的方式實現。

通過利用這種語法,我們最終得到了一個型別安全和無樣板解決方案。

自JDK10起

在JDK10之前,該方法只能在使用泛型型別引數時使用,但自從引入區域性變數型別推理以來,我們可以在區域性變數級別執行相同的操作:

var action = (Function<Integer, Integer> & Serializable) i -> i + 1;

 

相關文章