泛型是 JDK1.5 以后增加的,它可以帮助我们建立类型安全的集合,类型参数在编译后会被替换成 Object,运行时虚
拟机并不知道泛型。
泛型的好处
- 代码的可读性更好-(不用强制转换 )
- 程序更加安全 - (只要编译没有警告,运行时就不会出现ClassCastException异常)
泛型定义
泛型字符是可以使用任何字符的,但一般会采用这几个来标记:E、T、K、V、N、?
泛型标记 | 对应单词 | 说明 |
---|---|---|
E | Element | 在容器中使用,表示容器中的元素 |
T | Type | 表示普通的JAVA类 |
K | Key | 表示键,例如:Map中的键Key |
V | Value | 表示值 |
N | Number | 表示数值类型 |
? | 表示不确定的JAVA类型 |
泛型类
泛型类就是把泛型定义在类上,用户调用该类时才会确定类型,如:、<T、K、V>
语法结构
public class 类名<泛型表示符号>{
}
调用时如:
方法名<String> g = new 方法名<>();
泛型接口
语法结构
public interface 接口名<泛型表示符号>{
}
泛型方法
泛型方法是指将方法的参数类型定义成泛型,以便在调用时接收不同类型的参数。
调用泛型方法时,不需要像泛型类那样告诉编译器是什么类型,编译器可以自动推断出类型来,就是调用时跟普通方法一样直接调用就好。
非静态方法语法结构
public <泛型表示符号> void 方法名(泛型表示符号 arg){
}
public <泛型表示符号> 泛型表示符号 方法名(泛型表示符号 arg){
}
静态方法语法结构
public static <泛型表示符号> void 方法名(泛型表示符号 arg){
}
public static <泛型表示符号> 泛型表示符号 方法名(泛型表示符号 arg){
}
泛型方法与可变参数
如果定义泛型中参数有多个可以这样定义,这样就可以接收数组类型的参数了
语法结果:
public <泛型表示符号> void 方法名(泛型表示符号... args){
}
无界通配符与上下限定
无界通配符
就是"?",表示类型通配符,它只能在“<>”中使用,就是上面的泛型类或者方法将泛型类型符用?替代就好了
上限限定
上限限定表示通配符的类型是 T 类以及 T 类的子类或者 T 接口以及 T 接口的子接口。
public void showFlag(Generic<? extends Number> generic){
}
可以使用Number类以及Number的所有子类
下限限定
下限限定表示通配符的类型是 T 类以及 T 类的父类或者 T 接口以及 T 接口的父接口。
注意:该方法不适用泛型类。
public void showFlag(Generic<? super Integer> generic){
}
即Interger以及Integer的父类都可使用
泛型总结
泛型主要用于编译阶段,编译后生成的字节码 class 文件不包含泛型中的类型信息。 类型参数在编译后会被替换成 Object,运行时虚拟机并不知道泛型。因此,使用泛型时,如下两种情况是错误的:
- 基本类型不能用于泛型
Student<int> s;
这样是错的,要把int改成Integer,即
Student<Integr> s;
-
不能通过类型参数创建对象
T elm = new T(); 运行时类型参数 T 会被替换成 Object,无法创建 T 类型的对象,容易引起误解,所以在 Java 中不支持这种写法. -
注意下限限定不能使用与泛型类,只能用于泛型方法,上限限定两者都可