Java泛型構造函數

1.概述

咱們以前討論過Java Generics的基礎知識。在本文中,咱們將瞭解Java中的通用構造函數。 泛型構造函數是至少須要有一個泛型類型參數的構造函數。咱們將看到泛型構造函數並不都是在泛型類中出現的,並且並不是全部泛型類中的構造函數都必須是泛型。java

2.非泛型類

首先,先寫一個簡單的類:Entry,它不是泛型類:ide

public class Entry {
    private String data;
    private int rank;
}
複製代碼

在這個類中,咱們將添加兩個構造函數:一個帶有兩個參數的基本構造函數和一個通用構造函數。函數

2.1 基本構造器

Entry第一個構造函數:帶有兩個參數的簡單構造函數:單元測試

public Entry(String data, int rank) {
    this.data = data;
    this.rank = rank;
}
複製代碼

如今,讓咱們使用這個基本構造函數來建立一個Entry對象學習

@Test
public void givenNonGenericConstructor_whenCreateNonGenericEntry_thenOK() {
    Entry entry = new Entry("sample", 1);

    assertEquals("sample", entry.getData());
    assertEquals(1, entry.getRank());
}
複製代碼

2.2 泛型構造器

接下來,第二個構造器是泛型構造器:測試

public <E extends Rankable & Serializable> Entry(E element) {
    this.data = element.toString();
    this.rank = element.getRank();
}
複製代碼

雖然Entry類不是通用的,但它有一個參數爲E的泛型構造函數。this

泛型類型E是受限制的,應該實現RankableSerializable接口。spa

如今,讓咱們看看Rankable接口,下面是其中一個方法:翻譯

public interface Rankable {
    public int getRank();
}
複製代碼

假設咱們有一個實現Rankable接口的類——Productcode

public class Product implements Rankable, Serializable {
    private String name;
    private double price;
    private int sales;

    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }

    @Override
    public int getRank() {
        return sales;
    }
}
複製代碼

而後咱們能夠使用泛型構造函數和Product建立Entry對象:

@Test
public void givenGenericConstructor_whenCreateNonGenericEntry_thenOK() {
    Product product = new Product("milk", 2.5);
    product.setSales(30);

    Entry entry = new Entry(product);

    assertEquals(product.toString(), entry.getData());
    assertEquals(30, entry.getRank());
}
複製代碼

3.泛型類

接下來,咱們看一下泛型類:GenericEntry

public class GenericEntry<T> {
    private T data;
    private int rank;
}
複製代碼

咱們將在此類中添加與上一節相同的兩種類型的構造函數。

3.1 基礎構造器

首先,讓咱們爲GenericEntry類編寫一個簡單的非泛型構造函數:

public GenericEntry(int rank) {
    this.rank = rank;
}
複製代碼

儘管GenericEntry是泛型類,但這是一個簡單的,沒有任何參數的構造函數。

如今,咱們能夠使用此構造函數來建立GenericEntry

@Test
public void givenNonGenericConstructor_whenCreateGenericEntry_thenOK() {
    GenericEntry<String> entry = new GenericEntry<String>(1);

    assertNull(entry.getData());
    assertEquals(1, entry.getRank());
}
複製代碼

3.2 泛型構造器

接下來,在類中添加第二個構造函數:

public GenericEntry(T data, int rank) {
    this.data = data;
    this.rank = rank;
}
複製代碼

這是一個泛型構造函數,它有一個泛型類型T的數據參數。注意,咱們不須要在構造函數聲明中添加,由於它是隱含的。

如今,讓咱們測試一下通用構造函數:

@Test
public void givenGenericConstructor_whenCreateGenericEntry_thenOK() {
    GenericEntry<String> entry = new GenericEntry<String>("sample", 1);

    assertEquals("sample", entry.getData());
    assertEquals(1, entry.getRank());        
}
複製代碼

4.不一樣類型的泛型構造函數

在泛型類中,還有一個構造函數,其泛型類型與類的泛型類型不一樣:

public <E extends Rankable & Serializable> GenericEntry(E element) {
    this.data = (T) element;
    this.rank = element.getRank();
}
複製代碼

GenericEntry構造函數有類型爲E的參數,該參數與T類型不一樣。讓咱們看看它的實際效果:

@Test
public void givenGenericConstructorWithDifferentType_whenCreateGenericEntry_thenOK() {
    Product product = new Product("milk", 2.5);
    product.setSales(30);

    GenericEntry<Serializable> entry = new GenericEntry<Serializable>(product);

    assertEquals(product, entry.getData());
    assertEquals(30, entry.getRank());
}
複製代碼

注意:在示例中,咱們使用Product(E)建立Serializable(T)類型的GenericEntry,只有當類型E的參數能夠轉換爲T時,咱們才能使用此構造函數。

5.多種泛類型

接下來,咱們有兩個泛型類型參數的泛型類MapEntry

public class MapEntry<K, V> {
    private K key;
    private V value;

    public MapEntry(K key, V value) {
        this.key = key;
        this.value = value;
    }
}
複製代碼

MapEntry有一個兩個參數的泛型構造函數,每一個參數都是不一樣的類型。讓咱們用一個簡單的單元測試測試一下:

@Test
public void givenGenericConstructor_whenCreateGenericEntryWithTwoTypes_thenOK() {
    MapEntry<String,Integer> entry = new MapEntry<String,Integer>("sample", 1);

    assertEquals("sample", entry.getKey());
    assertEquals(1, entry.getValue().intValue());        
}
複製代碼

6.通配符

最後,咱們能夠在泛型構造函數中使用通配符:

public GenericEntry(Optional<? extends Rankable> optional) {
    if (optional.isPresent()) {
        this.data = (T) optional.get();
        this.rank = optional.get().getRank();
    }
}
複製代碼

在這兒,咱們在GenericEntry構造函數中使用通配符來綁定Optional類型:

@Test
public void givenGenericConstructorWithWildCard_whenCreateGenericEntry_thenOK() {
    Product product = new Product("milk", 2.5);
    product.setSales(30);
    Optional<Product> optional = Optional.of(product);

    GenericEntry<Serializable> entry = new GenericEntry<Serializable>(optional);

    assertEquals(product, entry.getData());
    assertEquals(30, entry.getRank());
}
複製代碼

請注意,咱們應該可以將可選參數類型(Product示例)轉換爲GenericEntry類型(Serializable示例)。

7.結束語

在本文中,咱們學習瞭如何在泛型和非泛型類中定義和使用泛型構造函數。

完整的源代碼能夠在GitHub獲取(點擊查看原文)。

原文連接:www.baeldung.com/java-generi…

做者:baeldung

譯者:Emma

推薦關注公衆號:鍋外的大佬

每日推送國外優秀的技術翻譯文章,勵志幫助國內的開發者更好地成長!

相關文章
相關標籤/搜索