Java泛型构造函数
点击左上角,关注:“锅外的大佬”
专注分享国外最新技术内容帮助每位开发者更优秀地成长
1.概述
我们之前讨论过
JavaGenerics
的基础知识。在本文中,我们将了解Java中的通用构造函数。泛型构造函数是至少需要有一个泛型类型参数的构造函数。我们将看到泛型构造函数并不都是在泛型类中出现的,而且并非所有泛型类中的构造函数都必须是泛型。2.非泛型类
首先,先写一个简单的类:Entry,它不是泛型类:
publicclassEntry{
privateString data;
privateint rank;
}
在这个类中,我们将添加两个构造函数:一个带有两个参数的基本构造函数和一个通用构造函数。
2.1. 基本构造器
Entry
第一个构造函数:带有两个参数的简单构造函数:publicEntry(String data,int rank){
this.data = data;
this.rank = rank;
}
现在,让我们使用这个基本构造函数来创建一个
Entry
对象@Test
publicvoid givenNonGenericConstructor_whenCreateNonGenericEntry_thenOK(){
Entry entry =newEntry("sample",1);
assertEquals("sample", entry.getData());
assertEquals(1, entry.getRank());
}
2.2. 泛型构造器
接下来,第二个构造器是泛型构造器:
public<E extendsRankable&Serializable>Entry(E element){
this.data = element.toString();
this.rank = element.getRank();
}
虽然
Entry
类不是通用的,但它有一个参数为 E
的泛型构造函数。泛型类型
E
是受限制的,应该实现 Rankable
和 Serializable
接口。现在,让我们看看
Rankable
接口,下面是其中一个方法:publicinterfaceRankable{
publicint getRank();
}
假设我们有一个实现
Rankable
接口的类—— Product
publicclassProductimplementsRankable,Serializable{
privateString name;
privatedouble price;
privateint sales;
publicProduct(String name,double price){
this.name = name;
this.price = price;
}
@Override
publicint getRank(){
return sales;
}
}
然后我们可以使用泛型构造函数和
Product
创建 Entry
对象:@Test
publicvoid givenGenericConstructor_whenCreateNonGenericEntry_thenOK(){
Product product =newProduct("milk",2.5);
product.setSales(30);
Entry entry =newEntry(product);
assertEquals(product.toString(), entry.getData());
assertEquals(30, entry.getRank());
}
3.泛型类
接下来,我们看一下泛型类:
GenericEntry
publicclassGenericEntry<T>{
private T data;
privateint rank;
}
我们将在此类中添加与上一节相同的两种类型的构造函数。
3.1. 基础构造器
首先,让我们为
GenericEntry
类编写一个简单的非泛型构造函数:publicGenericEntry(int rank){
this.rank = rank;
}
尽管
GenericEntry
是泛型类,但这是一个简单的,没有任何参数的构造函数。现在,我们可以使用此构造函数来创建
GenericEntry
:@Test
publicvoid givenNonGenericConstructor_whenCreateGenericEntry_thenOK(){
GenericEntry<String> entry =newGenericEntry<String>(1);
assertNull(entry.getData());
assertEquals(1, entry.getRank());
}
3.2. 泛型构造器
接下来,在类中添加第二个构造函数:
publicGenericEntry(T data,int rank){
this.data = data;
this.rank = rank;
}
这是一个泛型构造函数,它有一个泛型类型T的数据参数。注意,我们不需要在构造函数声明中添加,因为它是隐含的。
现在,让我们测试一下通用构造函数:
@Test
publicvoid givenGenericConstructor_whenCreateGenericEntry_thenOK(){
GenericEntry<String> entry =newGenericEntry<String>("sample",1);
assertEquals("sample", entry.getData());
assertEquals(1, entry.getRank());
}
4.不同类型的泛型构造函数
在泛型类中,还有一个构造函数,其泛型类型与类的泛型类型不同:
public<E extendsRankable&Serializable>GenericEntry(E element){
this.data =(T) element;
this.rank = element.getRank();
}
GenericEntry
构造函数有类型为 E
的参数,该参数与 T
类型不同。让我们看看它的实际效果:@Test
publicvoid givenGenericConstructorWithDifferentType_whenCreateGenericEntry_thenOK(){
Product product =newProduct("milk",2.5);
product.setSales(30);
GenericEntry<Serializable> entry =newGenericEntry<Serializable>(product);
assertEquals(product, entry.getData());
assertEquals(30, entry.getRank());
}
注意:在示例中,我们使用
Product(E)
创建 Serializable(T)
类型的 GenericEntry
,只有当类型 E
的参数可以转换为 T
时,我们才能使用此构造函数。5.多种泛类型
接下来,我们有两个泛型类型参数的泛型类
MapEntry
:publicclassMapEntry<K, V>{
private K key;
private V value;
publicMapEntry(K key, V value){
this.key = key;
this.value = value;
}
}
MapEntry
有一个两个参数的泛型构造函数,每个参数都是不同的类型。让我们用一个简单的单元测试测试一下:@Test
publicvoid givenGenericConstructor_whenCreateGenericEntryWithTwoTypes_thenOK(){
MapEntry<String,Integer> entry =newMapEntry<String,Integer>("sample",1);
assertEquals("sample", entry.getKey());
assertEquals(1, entry.getValue().intValue());
}
6.通配符
最后,我们可以在泛型构造函数中使用通配符:
publicGenericEntry(Optional<?extendsRankable> optional){
if(optional.isPresent()){
this.data =(T) optional.get();
this.rank = optional.get().getRank();
}
}
在这儿,我们在
GenericEntry
构造函数中使用通配符来绑定 Optional
类型:@Test
publicvoid givenGenericConstructorWithWildCard_whenCreateGenericEntry_thenOK(){
Product product =newProduct("milk",2.5);
product.setSales(30);
Optional<Product> optional =Optional.of(product);
GenericEntry<Serializable> entry =newGenericEntry<Serializable>(optional);
assertEquals(product, entry.getData());
assertEquals(30, entry.getRank());
}
请注意,我们应该能够将可选参数类型(Product示例)转换为
GenericEntry
类型(Serializable示例)。7.结束语
在本文中,我们学习了如何在泛型和非泛型类中定义和使用泛型构造函数。完整的源代码可以在
GitHub
获取(点击查看原文)。原文链接:https://www.baeldung.com/java-generic-constructors作者:baeldung译者:Emma
点击在看,和我一起帮助更多开发者!
阅读原文 最新评论
推荐文章
作者最新文章
你可能感兴趣的文章
Copyright Disclaimer: The copyright of contents (including texts, images, videos and audios) posted above belong to the User who shared or the third-party website which the User shared from. If you found your copyright have been infringed, please send a DMCA takedown notice to [email protected]. For more detail of the source, please click on the button "Read Original Post" below. For other communications, please send to [email protected].
版权声明:以上内容为用户推荐收藏至CareerEngine平台,其内容(含文字、图片、视频、音频等)及知识版权均属用户或用户转发自的第三方网站,如涉嫌侵权,请通知[email protected]进行信息删除。如需查看信息来源,请点击“查看原文”。如需洽谈其它事宜,请联系[email protected]。
版权声明:以上内容为用户推荐收藏至CareerEngine平台,其内容(含文字、图片、视频、音频等)及知识版权均属用户或用户转发自的第三方网站,如涉嫌侵权,请通知[email protected]进行信息删除。如需查看信息来源,请点击“查看原文”。如需洽谈其它事宜,请联系[email protected]。