搜索
查看
编辑修改
首页
UNITY
NODEJS
PYTHON
AI
GIT
PHP
GO
CEF3
JAVA
HTML
CSS
搜索
很楠不爱3
这个屌丝很懒,什么也没留下!
关注作者
热门标签
jquery
HTML
CSS
PHP
ASP
PYTHON
GO
AI
C
C++
C#
PHOTOSHOP
UNITY
iOS
android
vue
xml
爬虫
SEO
LINUX
WINDOWS
JAVA
MFC
CEF3
CAD
NODEJS
GIT
Pyppeteer
article
热门文章
1
AI大模型在自然语言处理中的应用:性能表现和未来趋势
2
tcpdump使用详解_source or destination address
3
使用AsyncTask+HttpClient_android asynctask+httpclient
4
3dsmax软件和maya软件各自的优劣势是什么?_max和maya的优缺点
5
径向基函数神经网络_神经网络(1)
6
若依框架去若依化,如果去除若依元素?
7
Unity3DVR开发—— XRInteractionToolkit(PicoNeo3、Oculus quest2)_pico neo 3开发教程
8
PostgreSQL的安装、配置与使用指南_postgresql安装
9
解决git pull时error: cannot lock ref 问题
10
SQL语句大全,所有的SQL都在这里
当前位置:
article
> 正文
对泛型的认识_symbol: variable roundingmode where t is a type-va
作者:很楠不爱3 | 2024-04-23 02:37:45
赞
踩
symbol: variable roundingmode where t is a type-variable: t extends number d
1.什么是泛型
一般的类和方法,只能使用
具体的类型
:
要么是基本类型,要么是自定义的类。
如果要
编写可以应用于多种类型的
代码,这种刻板的限制对代码的束缚就会很大
。
-----
来源《
Java
编程思想》对泛型的介绍。
泛型是在
JDK1.5
引入的新的语法,通俗讲,泛型:
就是
适用于许多许多类型
。从代码上讲,就是对类型实现了参数
化。
2.引出泛型
实现一个
类
,类中包含一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中某个
下标的值?
思路:
1.
我们以前学过的数组,只能存放指定类型的元素,例如:
int[] array = new int[10]; String[] strs = new
String[10];
2.
所有类的父类,默认为
Object
类。数组是否可以创建为
Object?
问题:以上代码实现后 发现
1.
任何类型数据都可以存放
2. 1
号下标本身就是字符串,但是确
编译报错。必须进行强制类型转换
虽然在这种情况下,当前数组任何数据都可以存放,但是,更多情况下,我们还是希望他只能够持有一种数据类
型。而不是同时持有这么多类型。
所以,泛型的主要目的:就是指定当前的容器,要持有什么类型的对象。让编译
器去做检查。
此时,就需要把类型,作为参数传递。需要什么类型,就传入什么类型(即指定特定类型的参数)
2.1
语法
class
泛型类名称
<
类型形参列表
>
{
//
这里可以使用类型参数
}
class
ClassName
<
T1
,
T2
, ...,
Tn
>
{
}
class
泛型类名称
<
类型形参列表
>
extends
继承类
/*
这里可以使用类型参数
*/
{
//
这里可以使用类型参数
}
class
ClassName
<
T1
,
T2
, ...,
Tn
>
extends
ParentClass
<
T1
>
{
//
可以只使用部分类型参数
}
代码实例
class
MyArray
<
T
>
{
public
T
[]
array
=
(
T
[])
new
Object
[
10
];
//1
public
T getPos
(
int
pos
) {
return this
.
array
[
pos
];
}
public
void
setVal
(
int
pos
,
T val
) {
this
.
array
[
pos
]
=
val
;
}
}
public class
TestDemo
{
public static
void
main
(
String
[]
args
) {
MyArray
<
Integer
>
myArray
=
new
MyArray
<>
();
//2
myArray
.
setVal
(
0
,
10
);
myArray
.
setVal
(
1
,
12
);
int
ret
=
myArray
.
getPos
(
1
);
//3
System
.
out
.
println
(
ret
);
myArray
.
setVal
(
2
,
"bit"
);
//4
}
}
代码解释:
1.
类名后的
<T>
代表占位符,表示当前类是一个泛型类
了解:
【规范】类型形参一般使用一个大写字母表示,常用的名称有:
E
表示
Element
K
表示
Key
V
表示
Value
N
表示
Number
T
表示
Type
S, U, V
等等
-
第二、第三、第四个类型
2.
注释
1
处,不能
new
泛型类型的数组
意味着:
课件当中的代码:
T[] array = (T[])new Object[10];
是否就足够好,答案是未必的。这块问题一会儿介
绍。(与泛型的擦除机制有关)
3.
注释
2
处,类型后加入
<Integer>
指定当前类型
4.
注释
3
处,不需要进行强制类型转换
5.
注释
4
处,代码编译报错,此时因为在注释
2
处指定类当前的类型,此时在注释
4
处,
编译器会在存放元素的时
候帮助我们进行类型检查。(即泛型存在的意义)
3.泛型类的使用
3.1
语法
泛型类
<
类型实参
>
变量名
;
//
定义一个泛型类引用
new
泛型类
<
类型实参
>
(
构造方法实参
);
//
实例化一个泛型类对象
3.2
示例
MyArray
<
Integer
>
list
=
new
MyArray
<
Integer
>
();
注意:泛型只能接受类,
所有的基本数据类型必须使用包装类
!
3.3
类型推导
(Type Inference)
MyArray
<
Integer
>
list
=
new
MyArray
<>
();
//
可以推导出实例化需要的类型实参为
String
当编译器可以根据上下文推导出类型实参时,
可以省略类型实参的填写
4.
裸类型
(Raw Type)
(了解)
4.1
说明
裸类型是一个泛型类但没有带着类型实参,例如
MyArrayList
就是一个裸类型
T
[]
ts
=
new
T
[
5
];
//
是不对的
泛型类
<
类型实参
>
变量名
;
//
定义一个泛型类引用
new
泛型类
<
类型实参
>
(
构造方法实参
);
//
实例化一个泛型类对象
MyArray
<
Integer
>
list
=
new
MyArray
<
Integer
>
();
MyArray
<
Integer
>
list
=
new
MyArray
<>
();
//
可以推导出实例化需要的类型实参为
String
4.裸类型
4.1
说明
裸类型是一个泛型类但没有带着类型实参,例如
MyArrayList
就是一个裸类型
MyArray list
=
new
MyArray
();
(定义时缺少了泛型)
注意:
我们不要自己去使用裸类型,
裸类型是为了兼容老版本的
API
保留的机制
下面的类型擦除部分,我们也会讲到编译器是如何使用裸类型的。
小结:
1.
泛型是将数据类型参数化,进行传递
2.
使用
<T>
表示当前类是一个泛型类。
3.
泛型目前为止的优点:
数据类型参数化,编译时自动进行类型检查和转换
本质
:其
本质是参数化类型,
也就是说所操作的数据类型被指定为一个参数(type parameter)这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
5.泛型如何编译的
5.1
擦除机制
那么,泛型到底是怎么编译的?这个问题,也是曾经的一个面试问题。泛型本质是一个非常难的语法,要理解好他
还是需要一定的时间打磨。
通过命令:
javap -c
查看字节码文件,所有的
T
都是
Object
。
在编译的过程当中,将所有的
T
替换为
Object
这种机制
,我们称为:
擦除机制
。
Java
的泛型机制是在编译级别实现的。编译器生成的字节码在
运行期间并不包含泛型的类型信息
有关泛型擦除机制的文章截介绍:
Java泛型擦除机制之答疑解惑 - 知乎
提出问题:
1
、
那为什么,
T[] ts = new T[5];
是不对的,编译的时候,替换为
Object
,不是相当于:
Object[] ts = new
Object[5]
吗?-->是这样,但是
编译器语法不允许将参数类型T直接进行实例化(如下图)
2
、类型擦除,一定是把
T
变成
Object
吗?(是的)
5.2
为什么不能实例化泛型类型数组
class
MyArray
<
T
>
{
public
T
[]
array
=
(
T
[])
new
Object
[
10
];//
留意这行代码所体现的问题
public
T getPos
(
int
pos
) {
return this
.
array
[
pos
];
}
public
void
setVal
(
int
pos
,
T val
) {
this
.
array
[
pos
]
=
val
;
}
public
T
[]
getArray
() {
return
array
;
}
}
public static
void
main
(
String
[]
args
) {
MyArray
<
Integer
>
myArray1
=
new
MyArray
<>
();
Integer
[]
strings
=
myArray1
.
getArray
()
;//我们在编译时默认将T转化为Object,所以getArray方法返回的数组为Object类型,用integer进行接收,明显是不安全的
}
/*
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;
at TestDemo.main(TestDemo.java:31)
*
原因:
替换后的方法为:将
Object[]
分配给
Integer[]
引用,程序报错。
public
Object
[]
getArray
() {
return
array
;
}
数组和泛型之间的一个重要区别是它们如何强制执行类型检查。
具体来说,数组在运行时存储和检查类型信息。然
而,泛型在编译时检查类型错误。
通俗讲就是:
返回的
Object
数组里面,可能存放的是任何的数据类型,可能是
String
,可能是
Person
,运行的时
候,直接转给
Intefer
类型的数组,编译器认为是不安全的。
正确的方式:
【了解即可】
class
MyArray
<
T
>
{
public
T
[]
array
;
public
MyArray
() {
}
/**
*
通过反射创建,指定类型的数组
* @param clazz
* @param capacity
*/
public
MyArray
(
Class
<
T
>
clazz
,
int
capacity
) {
array
=
(
T
[])
Array
.
newInstance
(
clazz
,
capacity
);
}
public
T getPos
(
int
pos
) {
return this
.
array
[
pos
];
}
public
void
setVal
(
int
pos
,
T val
) {
this
.
array
[
pos
]
=
val
;
}
public
T
[]
getArray
() {
return
array
;
}
}
public static
void
main
(
String
[]
args
) {
MyArray
<
Integer
>
myArray1
=
new
MyArray
<>
(
Integer
.
class
,
10
);
Integer
[]
integers
=
myArray1
.
getArray
();
}
6.泛型的上界
在定义泛型类时,有时需要对传入的类型变量做一定的约束,可以通过类型边界来约束
6.1
语法
6.2
示例
只接受
Number
的子类型作为
E
的类型实参
public
MyArray
() {
}
/**
*
通过反射创建,指定类型的数组
* @param clazz
* @param capacity
*/
public
MyArray
(
Class
<
T
>
clazz
,
int
capacity
) {
array
=
(
T
[])
Array
.
newInstance
(
clazz
,
capacity
);
}
public
T getPos
(
int
pos
) {
return this
.
array
[
pos
];
}
public
void
setVal
(
int
pos
,
T val
) {
this
.
array
[
pos
]
=
val
;
}
public
T
[]
getArray
() {
return
array
;
}
}
public static
void
main
(
String
[]
args
) {
MyArray
<
Integer
>
myArray1
=
new
MyArray
<>
(
Integer
.
class
,
10
);
Integer
[]
integers
=
myArray1
.
getArray
();
}
class
泛型类名称
<
类型形参
extends
类型边界
>
{
...
}
public class
MyArray
<
E
extends
Number
>
{
...
}
MyArray
<
Integer
>
l1
;
//
正常,因为
Integer
是
Number
的子类型
MyArray
<
String
>
l2
;
//
编译错误,因为
String
不是
Number
的子类型
error: type argument String is not within bounds of type-variable E
MyArrayList<String> l2;
^
where E is a type-variable:
E extends Number declared in class MyArrayList
了解:
没有指定类型边界
E
,可以视为
E extends Object
6.3
复杂示例
public class
MyArray
<
E
extends
Comparable
<
E
>>
{
...
}
E
必须是实现了
Comparable
接口的
7.泛型方法
7.3
使用示例
-
可以类型推导
Integer
[]
a
=
{ ... };
swap
(
a
,
0
,
9
);
String
[]
b
=
{ ... };
swap
(
b
,
0
,
9
);
7.4
使用示例
-
不使用类型推导
Integer
[]
a
=
{ ... };
Util
.
<
Integer
>
swap
(
a
,
0
,
9
);
String
[]
b
=
{ ... };
Util
.
<
String
>
swap
(
b
,
0
,
9
);
8.通配符
?
用于在泛型的使用,即为通配符
8.1
通配符解决什么问题
通配符是用来解决泛型无法协变的问题的
,
协变指的就是如果
Student
是
Person
的子类,那么
List<Student>
也应
该是
List<Person>
的子类。但是泛型是不支持这样的父子类关系的。
泛型
T
是确定的类型,一旦你传了我就定下来了,而通配符则更为灵活或者说是不确定,更多的是用于扩充
参数的范围
示例:
package
www
.
bit
.
java
.
test
;
class
Message
<
T
>
{
private
T message
;
public
T getMessage
() {
return
message
;
}
public
void
setMessage
(
T message
) {
this
.
message
=
message
;
}
}
public class
TestDemo
{
public static
void
main
(
String
[]
args
) {
Message
<
String
>
message
=
new
Message
() ;
message
.
setMessage
(
"
比特就业课欢迎您
"
);
fun
(
message
);
}
public static
void
fun
(
Message
<
String
>
temp
){
System
.
out
.
println
(
temp
.
getMessage
());
}
}
以上程序会带来新的问题,如果现在泛型的类型设置的不是
String
,而是
Integer
public class
TestDemo
{
public static
void
main
(
String
[]
args
) {
Message
<
Integer
>
message
=
new
Message
() ;
message
.
setMessage
(
99
);
fun
(
message
);
//
出现错误,只能接收
String
}
public static
void
fun
(
Message
<
String
>
temp
){
System
.
out
.
println
(
temp
.
getMessage
());
}
}
我们需要的解决方案:
可以接收所有的泛型类型,但是又不能够让用户随意修改。这种情况就需要使用通配符
"?"
来
处理
范例:使用通配符
public class
TestDemo
{
public static
void
main
(
String
[]
args
) {
Message
<
Integer
>
message
=
new
Message
() ;
message
.
setMessage
(
55
);
fun
(
message
);
}
//
此时使用通配符
"?"
描述的是它可以接收任意类型,但是由于不确定类型,所以无法修改
public static
void
fun
(
Message
<?>
temp
){
//temp.setMessage(100);
无法修改!
System
.
out
.
println
(
temp
.
getMessage
());
}
}
在
"?"
的基础上又产生了两个子通配符:
? extends
类:设置泛型上限
? super
类:设置泛型下限
8.2
通配符上界
语法:
<?
extends
上界
>
<?
extends
Number
>
//
可以传入的实参类型是
Number
或者
Number
的子类
9.包装类
在
Java
中,由于
基本类型不是继承自
Object
,为了在泛型代码中可以支持基本类型,
Java
给每个基本类型都对应了
一个包装类型。
9.1
基本数据类型和对应的包装类
声明:
本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:
https://www.wpsshop.cn/w/很楠不爱3/article/detail/471734
推荐阅读
article
Web3
Vue3
连接MetaMask(小狐狸)钱包
Request
of
type
‘
wallet
_...
"
Request
of
type
'
wallet
_
requestPermissions
'
already
pending
...
赞
踩
article
LTE
下行
物理层传输机制(6)-
下行
资源分配
方式(
Resource
Allocation
Type
)...
参考文献:(1)3GPP TS 36.212 V9.4.0 (2011-09) Multiplexing and cha...
赞
踩
article
HotSpot
Oop
/
Klass
模型_jstack no
suitable
match
for
...
基于:openjdk-8-src-b132-03_mar_2014
HotSpot
JVM 没有将Java对象直接通过虚拟...
赞
踩
article
Elasticsearch
实战:常见错误及详细
解决方案
_
elasticsearch
exceptio...
Elasticsearch
实战:常见错误及详细
解决方案
_
elasticsearch
exception
[
type
=ex...
赞
踩
article
Vue 中
Element
的
table
多选
表格
实现单选,并且
多选
表格
中表头的
多选
框不显示或隐藏_
el
-...
Vue 中
Element
的
table
多选
表格
实现单选,并且
多选
表格
中表头的
多选
框不显示或隐藏_
el
-
table
-colu...
赞
踩
article
Docker
容器
无法
启动
后,如何修改里面的
配置文件
_[
error
] [
my
-000067] [ser...
本来想修改
my
sql数据的
配置文件
,加了一个system_time_zone=CST 修改数据库时区,结果再次
启动
doc...
赞
踩
article
Consider defining a
bean
of
type
'org.springframew...
问题描述:使用Spring Boot最新版Spring Boot-2.0.3整合Redis,在启动项目时,遇到的一个bu...
赞
踩
article
JAVA
中
错误代码
是 the
public
type
must
be
def
in
ed
in
its...
一般是由于定义的
JAVA
类同文件名不一致; 解决方法: 1、把文件名修改同XYZ一样的名字; 2、把类名修改成同文...
赞
踩
article
The
type
XXXX
must
implement
the
inherited abstrac...
问题描述:新手学Java时会遇到定义了一个类使用接口时,在Eclipse中总会报The
type
XXX(类名) mus...
赞
踩
article
去除警告
Arr
a
yL
is
t
is
a
r
a
w
typ
e
_
a
rr
a
yl
is
t
is
a
r
a
w ty...
Eclipse里出现的警告:
Arr
a
yL
is
t
is
a
r
a
w
typ
e
. References to
generic
...
赞
踩
article
j
a
v
a
泛型问题 关于
警告
:
XX
is
a
r
a
w
type
【转】...
J
a
v
a
Tiger(J
a
v
a
5.0)-
a
rr
a
yl
is
t
is
a
r
a
w
type
2008-04-08 15:08 ...
赞
踩
article
List
is
a
r
a
w
type
. References to
generic
type
Lis...
List
is
a
r
a
w
type
. References to
generic
type
List
should
b...
赞
踩
article
L
is
t
is
a raw
type
.
References
to
generic
type
L
is
...
编译环境:Eclipse问题:编译集合类型
L
is
t
、Set、Map代码时,编译器出现下面的警告:
L
is
t
is
a ra...
赞
踩
article
QueryResult
is
a
r
a
w
type
. References to
generic
t...
QueryResult
is
a
r
a
w
type
. References to
generic
type
QueryR...
赞
踩
article
j
a
v
a
泛型问题 关于警告:XX
is
a
r
a
w
type
【转】_he
a
dobj
is
a
r
a
w...
J
a
v
a
Tiger(J
a
v
a
5.0)-
a
rr
a
yl
is
t
is
a
r
a
w
type
2008-04-08 15:08 ...
赞
踩
article
D
a
t
a
b
a
se 初见疑惑_-
a
rr
a
yl
is
t
is
a
r
a
w
t
ype
. reference...
D
a
t
a
b
a
se 作业项目难点记录_-
a
rr
a
yl
is
t
is
a
r
a
w
t
ype
.
references
t
o g...
赞
踩
article
eclipse
中如何去除警告:
Cl
a
ss
is
a
r
a
w
type
.
References
to ...
转自:https://blog.csdn.net/zwr_1022/
a
rticle/det
a
ils/78583872解决...
赞
踩
article
解决“
L
is
t
is
a
r
a
w
type
. References to
generic
type
...
在编写j
a
v
a
类中使用了
L
is
t
/M
a
p类,可是总是提示:
L
is
t
is
a
r
a
w
type
. References ...
赞
踩
article
去除j
a
v
a
泛型警告_去除警告
a
rr
a
yl
is
t
is
a
r
a
w
type
...
去除警告:Type s
a
fety: The method
a
dd(Object) belongs to the
r
a
w
...
赞
踩
article
Arr
a
yL
is
t
is
a
r
a
w
type
. References to generic typ...
Arr
a
yL
is
t
is
a
r
a
w
type
. References to generic
type
Arr
a
yL
is
...
赞
踩
相关标签
web3
jvm
elasticsearch
jenkins
大数据
搜索引擎
全文检索
搜索系统
检索系统
vue.js
javascript
前端
docker
容器
mysql
spring
spring boot-2.0.3
redis
merge
Exception
Java
类
接口
abstract