不同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是受限制的,应该实现rankable和serializable接口。
现在,让我们看看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.结束语
在本文中,我们学习了如何在泛型和非泛型类中定义和使用泛型构造函数。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。