码迷,mamicode.com
首页 > 编程语言 > 详细

Java泛型构造函数

时间:2020-09-08 20:58:16      阅读:57      评论:0      收藏:0      [点我收藏+]

标签:return   optional   void   可选参数   了解   val   绑定   create   his   

Java泛型构造函数

点击左上角,关注:“锅外的大佬”

专注分享国外最新技术内容
帮助每位开发者更优秀地成长

1.概述

我们之前讨论过 JavaGenerics的基础知识。在本文中,我们将了解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.结束语

在本文中,我们学习了如何在泛型和非泛型类中定义和使用泛型构造函数。完整的源代码可以在 GitHub获取(点击查看原文)。

原文链接:https://www.baeldung.com/java-generic-constructors

作者:baeldung

译者:Emma

推荐阅读:Spring Boot&ES记录日志
上篇好文:Java 8 Comparator:列表排序

点击在看,和我一起帮助更多开发者!
技术图片

Java泛型构造函数

标签:return   optional   void   可选参数   了解   val   绑定   create   his   

原文地址:https://blog.51cto.com/14901350/2525087

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!