目录
泛型基本概念
泛型可以理解为数据类型的占位符,处理的数据类型并不固定的。泛型可以使用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。在调用泛型时必须传入相应的类型。
泛型的使用
定义泛型
泛型字符可以是任何标识符,一般采用:E、T、K、V、N、?
泛型类型 | 对应单词 | 说明 |
E | Element | 在容器中使用,表示容器中的元素 |
T | Type | 表示普通的JAVA类 |
K | Key | 表示键 |
V | Value | 表示值 |
N | Number | 表示数值类型 |
? | 通配符,表示不确定的JAVA类型 |
泛型类
泛型类就是把泛型定义在类上,使用该类时,才把类型确定下来,泛型类的具体使用方法是在类的名称后添加一个或多个类型参数声明,如:<T>、<T,N>
/*public class 类名<泛型表示符号>{ }*/ public class Demo<T> { private T name; }
泛型接口
泛型接口和泛型类的声明方式一致,而泛型接口的具体类型需要在实现类中进行声明。
/*public interface 接口名<泛型表示符号> { }*/ public interface Demo<T> { void say(); }
public class Test implements Demo<String>{ @Override public void say(String name) { } }
如果创建Test对象用接口来修饰,例如:Demo demo=new Test();
此时调用say方法里面的参数类型是Object类型
解决这个的方法就是 Demo<String> demo=new Test();
泛型方法
泛型方法是指将方法的参数定义成泛型类型,有便于在调用时接收不同类型的参数。
public <泛型表示符号> void 方法名(泛型表示符号(或者是其他类型) 参数名){ } public <泛型表示符号> 泛型表示符号 方法名(泛型表示符号(或者是其他类型) 参数名){ } //第一种类型 public class Demo { public <T> void say(T name){ System.out.println(name); } } //第二种类型 public class Demo { public <T> T say(T name){ System.out.println(name); return name; } }
需要注意的是 静态方法中,不可以直接引用类的泛型
public class Demo<T> { //非静态方法可以直接引用类的泛型 public T say(T name){ System.out.println(name); return name; } /*编译错误 静态方法可以直接引用类的泛型 public static T say(){ }*/ }
通配符的上下限定
上限限定
上限限定表示通配符的类型是T类以及T类的子类或者是T接口以及T接口的子接口。
public class Demo<T> { public T say(T number){ System.out.println(number); return number; } }
public class Test { public void test(Demo<? extends Number> number){ System.out.println(number); } }
下限限定
下限限定表示通配符的类型是T类以及T类的父类或者是T接口以及T接口的父接口。
public class Demo<T> { public T say(T number){ System.out.println(number); return number; } }
public class Test { public void test(Demo<? super Integer> number){ System.out.println(number); } }
编码时的类型擦除
- 类型擦除指的是,编码是采用泛型写的类型参数,编译器会在编译时去掉。
- 泛型主要用于编译阶段,编译后生成的class文件不包含泛型中的类型信息,涉及类型转换仍然是普通的强制类型转换。类型参数在编译后被替换成Object,运行时虚拟机并不知道泛型。
泛型的意义
- 不用过多的强制转换,代码可读性更好(如果不使用泛型,我们可以使用Object类型来实现任意的参数类型,但是在使用时需要我们强制进行类型转换)
- 只要编译时编译器没有警告,运行时就不会出现ClassCastException异常
需要注意的是:
基本类型不可以用于泛型,即void say(int number){} 这样写是错误的,应为包装类Integer。