泛型
泛型的实现
泛型的优点
1、可以在编译的时候的时候,自动进行类型的检查
2、存放元素的时候,不需要强制类型转换。
3、编译的时候起作用,运行的时候被擦除
泛型的缺点
1、不能new泛型类型的数组
若要newT类型的数组则应: T[] t = (T[])new Object[];
2、基本类型不能作为泛型类型 的参数:如:int
泛型如何工作:
擦除机制:是在编译期间存在的一种机制,泛型的概念只存在在编译期间(在编译期间,将T擦除为Object,擦除不是替换)
class Group<T>{
public T[] elem;
public int size;
public Group(){
this.elem = (T[]) new Object[10];
this.size = 0;
}
public void add(T val){
this.elem[this.size]=val;
size++;
}
public T get (int n){
if ( n<0 ||n>=this.size) return null;
return this.elem[n-1];
}
}
public class Demo06 {
public static void main(String[] args) {
Group<Integer> lit= new Group<>();
lit.add(1);
lit.add(2);
System.out.println(lit.get(1));
Group lit= new Group<>();//此处也可以不使用泛型,此时默认为Object类型
}
}
泛型的参数(了解)
T 表示 Type
E 表示 Element
K 表示 Key
V 表示 Value
N 表示 Number
S, U, V 等等 - 第二、第三、第四个类型
泛型接口
泛型接口的实现
interface IA<T>{//接口不能实例化,接口命名加I 表示此类是接口
void act();
default void sleep(){//jdk1.8开始,接口中的方法也可以有具体的实现,但必须加default修饰
System.out.println("睡!!");
}
}
class B<T> implements IA<T> {
public void act() {//重写接口方法
System.out.println("站!!");
}
}
扩展:
interface IA<T,K>{//接口不能实例化,接口命名加I 表示此类是接口
void act();
default void sleep(){//jdk1.8开始,接口中的方法也可以有具体的实现,但必须加default修饰
System.out.println("睡!!");
}
}
class B<T,K,V> implements IA<T,V> {//实现的接口必须与原接口中泛型参数的数量一致,泛型的类型必须在实现此接口的泛型参数中出现。
public void act() {//重写接口方法
System.out.println("站!!");
}
}
class C<T> extends Stu{//也可继承一个不带泛型的类
}
泛型继承(类型边界)
如下,则T这个参数类型,只能为Number的子类类型,而在编译时,也将把T擦除为Number类型,而不是Object。
class Group<T extends Number> {
}
此时Number就叫做泛型的上界,而泛型是没有下界的。
泛型方法
class StaticMethod{
public static<T> T mathod(T val){
return val;
}
<T> T mathod1(T val){
return val;
}
public class Demo {
public static void main(String[] args) {
int a = StaticMethod.mathod(1);//此处使用类型推导
String str = StaticMethod.mathod("qqqq");//此处使用类型推导
int a = new StaticMethod().mathod1(1);//此处使用类型推导
String str = new StaticMethod().mathod1("qqqq");//此处使用类型推导
int a = new StaticMethod().<Integer>mathod1(1);//此处不使用类型推
int a = new StaticMethod().<String>mathod1("lit");//此处不使用类型推
}
}
通配符
上界与下界,例如
class CustomerList<T>{
public func(List<? extends Number> list) {
}
}
此时,func方法接收的返回值类型为List且里面存储的元素必须是Number子类类型的元素的类型,如:传入一个List<String>类型的,则会编译错误。
class CustomerList<T>{
public func(List<? super Integer> list) {
}
}
而此时,func方法接收的返回值类型为List且里面存储的元素必须是Number父类类型的元素的类型,如:传入一个List<Doublie>类型的,则会编译错误,此时应该传入Integer或Number或Object等
注意:泛型无下界!!!
泛型的父子类型
List<Number>不是List<Doublie>的父类型
List<Object>也不是List<Number>的父类型
List<?>是List<? extends Number>的父类型
List<? extends Number>List<Integer>的父类型
比较
如果某个类需要比较这个类的实例化对象,那么这个泛型类就需要重写equals方法,或者实现Comparable接口重写comparaTo方法,或实现Comparator接口重写compare方法
习题