泛型
泛型是在JDK 5中引入的一个新特性,其本质是参数化类型,也就是将具体的类型形参化,参数化的类型(可以称之为类型形参)在使用或者调用时传入具体的类型(类型实参),类似于调用方法时传入实参才确定方法形参的具体值。泛型的声明由一对尖括号和类型形参组成,类型形参定义在尖括号中间,定义类、接口和方法时使用泛型声明,定义出的类、接口和方法分别称为泛型类、泛型接口和泛型方法。
优点:
1.提高类型的安全性
2.消除强制类型转换
3.提高代码的复用性
4.提高运行时的效率
泛型接口
//接口
public interface MyInter<T> {
void set(T t);
T get(T t);
}
//接口继承类1
public class MyInterImpl implements MyInter<String>{
@Override
public void set(String s) {
}
@Override
public String get(String s) {
return null;
}
}
//接口继承类2
public class MyInterImpl2<T> implements MyInter<T>{
@Override
public void set(T t) {
}
@Override
public T get(T t) {
return null;
}
}
泛型类
public class Goods<E> {
private E e;
public Goods() {
}
public Goods(E e){
this.e=e;
}
public E get(){
return this.e;
}
public void set(E e){
this.e=e;
}
}
泛型方法(依据调用者传递的值确定数据类型)
泛型方法是将类型形参的声明放在修饰符和返回类型之间的方法。在Java程序中,定义泛型方法常用的格式如下所示:
[访问权限修饰符][static] [final]<类型形参>返回值类型方法名(形式参数列表){}
ps:
(1) 访问权限修饰符(包括private、public、protected)、static和final都必须写在类型形参列表的前面。
(2)返回值类型必须写在类型形参列表的后面。
(3)泛型方法可以在泛型类中,也可以在普通类中。
(4)泛型类中的任何方法本质上都是泛型方法,所以在实际使用中很少会在泛型类中再用上面的形式来定义泛型方法。
(5)类型形参可以用在方法体中修饰局部变量,也可以修饰方法的返回值。
(6)泛型方法可以是实例方法(没有用static修饰,也叫非静态方法)也可以是静态方法。
类型通配符
public static void main(String[] args) {
Person<?> per = new Person<String>("M1");
per = new Person<Integer>(666);
per = new Person<Boolean>(true);
//报错,String类型无法转换为Object类型
Person<Object> per1 = new Person<String>("M2");
}
/*会出现上图所示的编译异常,是因为泛型中,类名和泛型的声明是一个整体类型,Person<Object>并不是Person<String的父类。*/
设定类型通配符的上限
当使用Person<?>时,表示这个泛型Person可以接收所有类型的类型实参。但有时候不想让某个泛型类接收所有类型的类型实参,只想接收指定的类型及其子类,这个时候可以为类型通配符设定上限。设定类型通配符的上限的语法格式如下所示:
<? extends 类名>
/*
* ? extends 类名 规定了上限
* 传递的是 该类类型或其子类类型
*
* ?super 类名 规定了下限
* 传递的是 该类类型或其父类类型
* */