标签:return optional void 可选参数 了解 val 绑定 create his
Java泛型构造函数点击左上角,关注:“锅外的大佬”
专注分享国外最新技术内容
帮助每位开发者更优秀地成长
我们之前讨论过 JavaGenerics的基础知识。在本文中,我们将了解Java中的通用构造函数。泛型构造函数是至少需要有一个泛型类型参数的构造函数。我们将看到泛型构造函数并不都是在泛型类中出现的,而且并非所有泛型类中的构造函数都必须是泛型。
首先,先写一个简单的类:Entry,它不是泛型类:
public
class
Entry
{
private
String
data
;
private
int
rank
;
}
在这个类中,我们将添加两个构造函数:一个带有两个参数的基本构造函数和一个通用构造函数。
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
());
}
接下来,第二个构造器是泛型构造器:
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
());
}
接下来,我们看一下泛型类: GenericEntry
public
class
GenericEntry
<
T
>
{
private
T data
;
private
int
rank
;
}
我们将在此类中添加与上一节相同的两种类型的构造函数。
首先,让我们为 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
());
}
接下来,在类中添加第二个构造函数:
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
());
}
在泛型类中,还有一个构造函数,其泛型类型与类的泛型类型不同:
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时,我们才能使用此构造函数。
接下来,我们有两个泛型类型参数的泛型类 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
());
}
最后,我们可以在泛型构造函数中使用通配符:
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示例)。
在本文中,我们学习了如何在泛型和非泛型类中定义和使用泛型构造函数。完整的源代码可以在 GitHub获取(点击查看原文)。
原文链接:https://www.baeldung.com/java-generic-constructors
作者:baeldung
译者:Emma
推荐阅读:Spring Boot&ES记录日志
上篇好文:Java 8 Comparator:列表排序
点击在看,和我一起帮助更多开发者!
标签:return optional void 可选参数 了解 val 绑定 create his
原文地址:https://blog.51cto.com/14901350/2525087