Java泛型構造函數


1.概述

我們之前討論過Java Generics的基礎知識。在本文中,我們將了解Java中的通用構造函數。 泛型構造函數是至少需要有一個泛型類型參數的構造函數。我們將看到泛型構造函數並不都是在泛型類中出現的,而且並非所有泛型類中的構造函數都必須是泛型。

2.非泛型類

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

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的泛型構造函數。

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

現在,讓我們看看Rankable接口,下面是其中一個方法:

public interface Rankable { public int getRank(); } 復制代碼

假設我們有一個實現Rankable接口的類——Product

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

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

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

 




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM