文章目录
泛型
1.泛型简介
1.1什么是泛型
泛型本质就是“数据类型参数化”,处理的数据类型不是固定的,而是作为参数传入。
- 参数化类型,通俗的讲:
- 把类型当参数一样传递
- <数据类型>只能是引用类型
1.2泛型的好处
- 读性更高 不用强制转换
- 程序更加安全 只要编译时期没有警告,运行时期就不会出现ClassCastException 异常
1.3类型擦除
编码时采用泛型写的类型参数,编译器会在编译时去掉,这称之为“类型擦除”。
泛型主要用于编译阶段,编译后生成的字节码class文件不包含泛型中的类型信息,涉及类型转换仍然是普通的强制类型转换。类型参数在编译后会被替换成object,运行时虚拟机并不知道泛型。
泛型主要是方便了程序员的代码编写,以及更好的安全性检测。
2.泛型的使用
2.1定义泛型
泛型字符可以用任意字符标记,一般采用E,T,K,V,N,?。
字符标记 | 代表单词 | 说明 |
---|---|---|
E | Element | 在容器中使用,表示容器中的元素 |
T | Type | 普通java类 |
K | Key | 表示键,例如Map中的Key |
V | Value | 表示值 |
N | Number | 表示数值类型 |
? | 表示不确定java类型 |
2.2泛型类
泛型类就是把泛型定义在类上,用户使用该类的时候,才把类型明确下来。泛型类的具体使用方法是在类的名称后添加一个或多个类型参数声明,如:< T >、<T,K,V>
语法结构:
public class 类名<泛型表示符号>{}
2.3泛型接口
泛型接口和泛型类的声明方式一致。泛型接口的具体类型需要在实现类中进行声明。
语法结构:
public interface 接口名<泛型表示符号>{}
2.4泛型方法
泛型类中所定义的泛型,在方法中也可以使用。但是,我们经常需要仅仅在某一个方法上使用泛型,这时候可以使用泛型方法。
泛型方法是指将方法的参数类型定义成泛型,以便在调用时接收不同类型的参数。类型参数可以有多个,用逗号隔开,如:<K,V>。定义时,类型参数一般放到返回值前面。
调用泛型方法时,不需要像泛型类那样告诉编译器是什么类型,编译器可以自动推断出类型来。
2.4.1非静态方法
语法结构
public <泛型表示符号> 泛型表示符号 getName(泛型表示符号 name){}
2.4.2静态方法
静态方法不能访问到类中的定义的泛型
语法结构
public static <泛型标识符号> 泛型表示符号 getName(泛型表示符号 name){}
2.4.3泛型方法与可变参数
语法结构
public <泛型表示符号> 泛型表示符号 getName(泛型表示符号... args){}
2.5通配符和上下限定
2.5.1无界通配符
"?“表示类型通配符,用于代替具体类型。它只能在”<>"中使用。解决类型不确定问题。
语法结构
public void showFlag(Generic<?> generic){}
2.5.2通配符的上限限定
上限限定表示通配符的类型是T类以及T类的子类或者T接口以及T接口的子接口。
-
该方式同样适用于与泛型的上限限定。
语法结构
public void showFlag(Generic<? extends Number> generic){}
2.5.3通配符的下限限定
下限限定表示通配符的类型是T类以及T类的父类或者Ⅰ接口以及T接口的父接口。
- 注意:该方法不适用泛型类。
语法结构
public void showFlag(Generic<? super Integer> generic){}
3.泛型总结
泛型主要用于编译阶段,编译后生成的字节码class文件不包含泛型中的类型信息。类型参数在编译后会被替换成object,运行时虚拟机并不知道泛型。因此,使用泛型时,如下几种情况是错误的:
1.基本类型不能用于泛型。
Test <int> t;
这样写法是错误,我们可以使用对应的包装类;
Test<lnteger > t;
2.不能通过类型参数创建对象。
T elm=new T();
运行时类型参数T会被替换成Object,无法创建T类型的对象,容易引起误解,所以在Java中不支持这种写法。
- 学习来自于西安加中实训