- 泛型简介
- 概念
- 好处
- 类型擦除
- 泛型使用
- 定义泛型
- 泛型类
- 泛型接口
- 泛型方法
- 非静态方法
- 静态方法
- 泛型方法和可变参数
- 通配符的使用
- 通配符的上限限定
- 通配符的下限限定
- 总结
- 泛型的本质就是数据类型的参数化,处理的数据类型不是固定的,而是可以作为参数传入。
- 我们可以把“泛型”理解为数据类型的一个占位符(类似:形式参数),即告诉编
译器,在调用泛型时必须传入实际类型。 - 这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
- 可以让编译器帮助我们识别强制类型转换时可能引起的错误,自动转换增加安全性和可读性
编码时采用泛型写的类型参数,编译器会在编译时去掉,这称之为“类型擦除”。
泛型使用 定义泛型泛型主要用于编译阶段,编译后生成的字节码 class 文件不包含泛型中的类型信息,涉及类型转换仍然是普通的强制类型转换。 类型参数在编译后会被替换成 Object,运行时虚拟机并不知道泛型。
- 泛型类就是把泛型定义在类上,用户使用该类的时候,才把类型明确下来。
多个标识符用逗号隔开
public class 类名<泛型标识符>、<泛型标识符>{
}
package generic;
public class testGeneric {
public static void main(String[] args) {
// TODO Auto-generated method stub
Generic generic = new Generic<>();
generic.setFlag("admin");
String flag = generic.getFlag();
System.out.println(flag);
Generic generic2 = new Generic<>();
generic2.setFlag(123);
Integer flag1 = generic2.getFlag();
System.out.println(flag1);
System.out.println(flag1.TYPE);
}
}
admin 123 int泛型接口
- 泛型接口和泛型类的声明方式一致。泛型接口的具体类型需要在实现类中进行声明。
多个标识符用逗号隔开
public interface 接口名<泛型标识符>、<泛型标识符>{
}
- 泛型接口
public interface Igeneric{ T getName(T name); }
- 实现泛型接口的类
public class IgenericImpl implements Igeneric{ @Override public String getName(String name) { // TODO Auto-generated method stub return name; } }
- 测试类
- 通过接口实现类创建对象时,按照实现类的参数类型确定
- 直接通过接口修饰时需要确定参数类型,不指定之前时Object类型
IgenericImpl igenericImpl = new IgenericImpl();
String name = igenericImpl.getName("ssc");
System.out.println(name);
Igeneric igenericImpl2 = new IgenericImpl();
String name1 = igenericImpl2.getName("sdasdad");
System.out.println(name1);
泛型方法
- 泛型方法是指将方法的参数类型定义成泛型,以便在调用时接收不同类型的参数。类型参数可以有多个,用逗号隔开,如:
。定义时,类型参数一般放到返回值前面。
只要定义了泛型方法,方法的参数和内部都可以使用该泛型
public <泛型表示符号> void getName(泛型表示符号 name){
}
public <泛型表示符号> 泛型表示符号 getName(泛型表示符号 name){
}
package generic;
public class MethodGeneric {
public static void main(String[] args) {
// TODO Auto-generated method stub
MethodGeneric methodGeneric = new MethodGeneric();
//不需要写出参数类型
methodGeneric.setName("ssc");
methodGeneric.setName(123);
System.out.println(methodGeneric.getName(456));
System.out.println(methodGeneric.getName("ssc1"));
}
//定义了一个泛型方法
public void setName(T name) {
System.out.println(name);
}
public T getName(T name){
return name;
}
}
ssc 123 456 ssc1静态方法
- 静态方法无法访问类上定义的泛型;如果静态方法操作的引用数据类型不确定的时候,必须要将泛型定义在方法上。
public static <泛型表示符号> void setName(泛型表示符号 name){
}
public static <泛型表示符号> 泛型表示符号 getName(泛型表示符号 name){
}
//静态方法中测试泛型 //有返回值 public staticvoid getFlag(T flag) { System.out.println(flag); } //无返回值 public static T setFlag1(T flag) { return flag; }
MethodGeneric.getFlag(132);
String flag12 = MethodGeneric.setFlag1("123456");
System.out.println(flag12);
132 123456泛型方法和可变参数
public <泛型表示符号> void showMsg(泛型表示符号... agrs){
}
//泛型方法可变参数 publicvoid method(T...args) { for(T t:args) { System.out.println(t); } }
//可变参数类型遍历数组
MethodGeneric methodGeneric2 = new MethodGeneric();
String[] arr = new String[] {"a","b","c"};
Integer[] a = new Integer[] {1,2,3};
methodGeneric2.method(arr);
methodGeneric2.method(a);
a b c 1 2 3通配符的使用
- “?”表示类型通配符,用于代替具体的类型。它只能在“<>”中使用。可以解决当具体类型不确定的问题。
public void showFlag(Generic> generic){
}
package generic;
public class Wildcard {
public static void main(String[] args) {
ShowMsg uMsg = new ShowMsg();
Generic generic = new Generic<>();
generic.setFlag(20);
uMsg.showFlag(generic);
Generic generic1 = new Generic<>();
generic1.setFlag(30);
uMsg.showFlag(generic1);
}
}
class ShowMsg{
//?通配符
public void showFlag(Generic> generic) {
System.out.println(generic.getFlag());
}
// public void showFlag(Generic generic) {
// System.out.println(generic.getFlag());
// }
}
20 30通配符的上限限定
- 上限限定表示通配符的类型是 T 类以及 T 类的子类或者 T 接口以及 T 接口的子接口。该方式同样适用于与泛型的上限限定。<>
public void showFlag(Generic extends Number> generic){
}
public class Wildcard {
public static void main(String[] args) {
ShowMsg uMsg = new ShowMsg();
//被限定在Number的子类
// Generic generic2 = new Generic<>();
// generic2.setFlag(40);
// uMsg.showFlag(generic2);
}
}
class ShowMsg{
//?通配符
public void showFlag(Generic extends Number> generic) {
System.out.println(generic.getFlag());
}
}
Exception in thread "main" java.lang.Error: Unresolved compilation problems:通配符的下限限定
- 下限限定表示通配符的类型是 T 类以及 T 类的父类或者 T 接口以及 T 接口的父接口。
注意:该方法不适用泛型类。
public void showFlag(Generic super Number> generic){
}
public class Wildcard {
public static void main(String[] args) {
ShowMsg uMsg = new ShowMsg();
//被限定在Integer的父类
// Generic generic2 = new Generic<>();
// generic2.setFlag(40);
// uMsg.showFlag1(generic2);
}
class ShowMsg{
//?通配符下限
public void showFlag1(Generic super Integer> generic) {
System.out.println(generic.getFlag());
}
}
Exception in thread "main" java.lang.Error: Unresolved compilation problems:总结
- 泛型最大的作用就是在编译时类型安全的问题,仅在编译阶段有效,结束后会自动转为Object类
- 使用泛型时,如下几种情况是错误的:
- 不能创建基本类型
Test t; 这样写法是错误,我们可以使用对应的包装类;Test t ; - 不能通过类型参数创建对象
T elm = new T(); 运行时类型参数 T 会被替换成 Object,无法创建 T 类型的对 象,容易引起误解,所以在 Java 中不支持这种写法
- 不能创建基本类型



