泛型
泛型是 jdk1.5引入的一个新特性,提供编译期类型安全检测机制。该机制允许在编译时检测。检测存入集合中的类是是否合法,通过参数化类型,将数据类型作为一个参数来引入。
当提到参数的时候,需要想到参数有形参和实参
泛型:参数化类型 将类型由原来的具体的类型参数化,在使用是传入具体的类型。
泛型可以用在类上(泛型类),接口(泛型接口),方法(泛型方法)上
泛型的定义格式:
<类型>:指定类型的格式
<类型1,类型2,...> 多类型的格式
泛型的使用:
在使用时传入具体的类型 此处需要注意:传入的类型只能是引用类型
泛型的好处:
1 可以在编译期 来检测数据类型 从而将错误的检测时机提前到编译期
2 将来在使用集合中的对象时,可以避免对对象的强制转换。
泛型的体会:
/*
需求:用TreeSet集合存储多个学生信息(姓名,语文成绩,数学成绩),并遍历该集合
要求:按照总分从高到低出现
*/
public class GenericDemo_01 {
public static void main(String[] args) {
//jdk7以前
//Set<Student> students = new TreeSet<Student>();
//jdk7以后可以在new的时候 省略泛型的指定
//set集合的排序使用定制排序
Set<Student> set = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student stu1, Student stu2) {
return (stu1.getChinese() +stu1.getMath()) -(stu2.getChinese() +stu2.getMath()) ;
}
});
Student st1 = new Student("张三",80,90);
Student st2= new Student("李四",89,92);
Student st3 = new Student("王五",75,68);
set.add(st1);
set.add(st2);
set.add(st3);
//迭代
Iterator<Student> iter = set.iterator();
while(iter.hasNext()){
Student student = iter.next();
System.out.println(student);
}
System.out.println("----------------");
//使用增强for进行遍历
for(Student student : set){
System.out.println(student);
}
}
}
泛型类
修饰符 class 类名<类型>
常用的泛型参数:E T K V
自定义泛型类:
// 这是一个泛型类 T 表示该类将使用一个数据类型为T 可以在类中使用该参数来表示一种数据类型
public class Generic<T> {
private T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
自定义泛型类的使用
public static void main(String[] args) {
//自定义泛型类的使用
Generic<String> generic = new Generic<>();
generic.setT("admin");
System.out.println(generic.getT().toUpperCase());//此时get所得到的是String 可以使用String类提供的所有方法
Generic<Double> generic1 = new Generic<>();
generic1.setT(100.2);
generic1.setT(56.6);
System.out.println(generic1.getT());
}
泛型方法
泛型方法的格式:修饰符 <类型> 返回值类型 方法名称(形参列表)
// 这是一个泛型类 T 表示该类将使用一个数据类型为T 可以在类中使用该参数来表示一种数据类型
public class Generic<T> {
private T t;
public T getT() {
return t;
}
// 不是泛型方法
public void setT(T t) {
this.t = t;
}
//这才是泛型方法
public <E> void show(E e){
System.out.println();
}
}
//这才是泛型方法 E 对应将来调用时传入的实参类型 T 对应的是在创建泛型类对象时 指定的类型
public <E> void show(E e,T t){
System.out.println(e+"---"+t);
}
//这也是一个泛型方法 E 对应调用时的传入的实参类型 泛型参数不仅可以作为方法的参数类型还可以作为返回值类型
public <E> E show(E e){
return e;
}
使用:
// generic.show("蓝桥",100);
generic.show(100,"蓝桥");
generic.show(true,"admin");
//泛型方法返回值类型为泛型的方法调用
String s = generic1.show("String");
System.out.println(s);
泛型类中可以没有泛型方法 ,同时存在泛型方法的类 也不一定时泛型类
泛型接口
格式:修饰符 interface 接口名<类型>{}
泛型接口的定义
//泛型接口
public interface IGeneric<T> {
void test(T t);//这是普通方法
<E> E show(E e);//泛型方法
}
普通类实现泛型接口(了解)
public class GenericImpl implements IGeneric<String> {
@Override
public void test(String s) {
System.out.println(s);
}
@Override
public <E> E show(E e) {
return e;
}
}
测试
public class IGenericTest {
public static void main(String[] args) {
IGeneric<String> generic = new GenericImpl();
generic.test("hello ");
String s = generic.show("world");
System.out.println(s);
}
}
使用泛型类来实现泛型接口(推荐使用)
public class GenericImpl<T> implements IGeneric<T> {
@Override
public void test(T t) {
System.out.println(t);
}
@Override
public <E> E show(E e) {
return e;
}
}
多泛型
//泛型接口
public interface IGeneric<T,E> {
void test(T t);//这是普通方法
<E> E show(E e);//泛型方法
}
public class GenericImpl<T,E> implements IGeneric<T,E> {
@Override
public void test(T t) {
System.out.println(t);
}
@Override
public <E> E show(E e) {
return e;
}
}
泛型接口中不一定存在泛型方法 存在泛型方法的接口 也不一定是泛型接口
泛型通配符
通配符:<?>
List<?> 表示存储 的数据类型是位置类型 它可以匹配任何类型
通配符上限:List<? extends Number> 表示的类型为Number及其子类
通配符下限:List<? super Number> 表示的类型为Number及其父类
基本使用:
public static void main(String[] args) {
// 通配符的使用 以下声明List<?>仅表示各种泛型List的父类 不能给其中添加元素
List<?> list1 = new ArrayList<>();
List<?> list2 = new ArrayList<Object>();
List<?> list3 = new ArrayList<Integer>();
//通配符上限 以下声明List<? extends Number >仅表示各种泛型List的父类 上限 为Number 不能给其中添加元素
List<? extends Number > list4 = new ArrayList<Number>();
List<? extends Number> list5= new ArrayList<Integer>();
//通配符下限
List<? super Number > list6 = new ArrayList<Number>();
List<? super Number> list7= new ArrayList<Object>();
// List<? super Number> list8= new ArrayList<Integer>();
}