原创

Java泛型


泛型笔记

java中的泛型意思:类型限定的意思

本质:

  1. 把对象/集合里面的元素的类型推迟到创建集合的时候体现出来
  2. 类型参数化

泛型的格式

​ <数据类型> 这个数据类型只能是引用数据类型,不能是基本数据类型

使用的格式

​ 数据类型<泛型的类型> 对象 = new 数据类型<数据类型>();

JDK1.7之后,有了新特性 ---> 泛型推断,可以根据左边的泛型类型来判断右边的泛型类型,也就是右边可以不加泛型

泛型类

  1. 泛型类的定义

    //泛型是加载类型名后面的
    public class FanXingClass<T,E> {
    	T t;
        E e;
    }
    

    **<>**里面的是泛型形参

    T 就是泛型的形参名称,名称只要遵循java的标识符规范就可以 。 例如:int a; 就和这个 a 是一样的意思

    通常泛型形参都是一个大写字母,用的最多的就是T,E

    泛型可以同时定义多个,多个之间用 ”“隔开

    <T ,E> 这里的T E可以理解成Object

    使用:

    //定义一个泛型类
    public class FanXingClass<T> {
        T t;
    
        public T getT() {
            return t;
        }
    
        public void setT(T t) {
            this.t = t;
        }
    }
    

    使用这个泛型类:

    public class Test1 {
        public static void main(String[] args) {
            FanXingClass fanXingClass = new FanXingClass();		//这里没有定义泛型的类型
            fanXingClass.setT(1);
            System.out.println(fanXingClass.getT());
            fanXingClass.setT("a");
            System.out.println(fanXingClass.getT());			//没有定义泛型的话返回的是Object类型的值
        }
    }
    
    public class Test2 {
        public static void main(String[] args) {
            FanXingClass<String> fanXingClass = new FanXingClass<String>();		//这里没定义泛型的类型是String
            fanXingClass.setT("a");
            System.out.println(fanXingClass.getT());			//返回的是String类型的值
        }
    }
    
    public class Test3 {
        public static void main(String[] args) {
            FanXingClass<Integer> fanXingClass = new FanXingClass<Integer>();	//这里定义泛型的类型是Integer
            fanXingClass.setT(1);
            System.out.println(fanXingClass.getT());		//返回的是Integer类型的值
        }
    }
    

泛型接口

​ 接口中的属性都是常量,明确的量,泛型是不明确的

public interface FanXingInter<T,E> {
    void method1(T t);   //泛型在接口中只能这样定义
}

​ 使用例子

public interface FanXingInter<T,E> {
    void method1(T t);
    void method2(E e);
}

​ 实现方法 (1)

public class FanXingInterImpl implements FanXingInter {
    @Override
    public void method1(Object o) {

    }

    @Override
    public void method2(Object o) {

    }
}

​ 实现接口的时候,如果泛型的具体类型没有明确,没有限定 ---> implements FanXingInter 这种,那么这个类就变成了泛型类

​ 实现方法(2)

public class FanXingInterImpl<T,E> implements FanXingInter<T,E> {
    @Override
    public void method1(T t) {
        
    }

    @Override
    public void method2(E e) {

    }
}
//使用
public class Test {

    public static void main(String[] args) {
        FanXingInterImpl<String,String> fanXingInterImpl = new FanXingInterImpl();
    }
    
}

​ 实现方法(3) 明确了类型 ---> implements FanXingInter<String,Integer>

public class FanXingInterImpl<String,Integer> implements FanXingInter<String,Integer> {
    @Override
    public void method1(String string) {

    }

    @Override
    public void method2(Integer integer) {

    }
}
//使用
public class Test2 {

    public static void main(String[] args) {
        FanXingInterImpl fanXingInter = new FanXingInterImpl();
    }
    
}

泛型方法

​ 泛型方法的泛型是加在返回值类型前面

public class FanXingMethod {
    public void method1(){					//普通的方法

    }
    public <T> void method2(){				//加泛型的方法
        
    } 
}

​ 使用例子

public class FanXingMethod {
    public <T,E> void method(T t){
        System.out.println(t);
    }
}
public class Test3 {
    public static void main(String[] args) {
        FanXingMethod fanXingMethod = new FanXingMethod();
        fanXingMethod.method2("a");
        fanXingMethod.method2(1);
    }
}

泛型通配符

作用:匹配

种类:

​ ? 任意通配符

​ ? extends E 向下限定,上限是E

​ ? super E 向上限定,下限是E

public class Person {
    public void eat(){
        System.out.println("Person.....eat.....");
    }
}
public class Student extends Person {
    @Override
    public void eat() {
        System.out.println("Student.....eat.....");
    }
}
public class Test4 {
    public static void main(String[] args) {
        //泛型通配符不是用在定义对象上
        //用在方法的形参上
        //ArrayList<?> list1 = new ArrayList();					//所有
        //list1.add("");  //这里是会报错的
        //ArrayList<? extends Person>  list2 = new ArrayList();	//向下限定 Person子类 list里只能添加Person子类
        //ArrayList<? super Student>  list3 = new ArrayList<>();	//向上限定 student父类 list里只能添加student父类
        //以上都是错误的,泛型通配符不应该在那里定义  一下才是正确的
        
        //这样使用
        ArrayList<Student> list = new ArrayList();
        list.add(new Student());
        method(list);

        ArrayList<Person> list1 = new ArrayList<>();
        list1.add(new Student());  //多态
        method(list1);
    }
    //应该这样定义
    public static void method(ArrayList<?> list){
        for (Object object: list) {
            System.out.print(object+" ");
        }
    }
}

为什么要用泛型通配符

​ 因为集合没有协变(但是数组可以协变)

​ 协变:妥协 改变

//数组的协变演示
public class Test4 {
    public static void main(String[] args) {
        
        //数组的协变
        Person[] person = new Person[2];
        person[0] = new Person();
        person[1] = new Person();
        method2(person);
        
        Student[] students = new Student[2];
        students[0] = new Student();
        students[1] = new Student();
        method2(students);
    }

    public static void method2(Person[] people){
        for(Person person : people){
            System.out.println(person);
        }
    }
}
//集合的不可协变性
public class Test4 {
    public static void main(String[] args) {

        //集合的不可协变性
        ArrayList<Student> students1 = new ArrayList<>();
        ArrayList<Person> persons = new ArrayList<>();
        method3(persons);
        //method3(students1);  //这里是报错的   不可以改变,必须一一对应的  这里只能传 Person类型的

    }

    public static void method3(ArrayList<Person> personlist){
        for (Person person : personlist){
            System.out.println(person);
        }
    }
}

因为集合的不可协变性,所以我们需要使用泛型通配符

public class Test5 {
    public static void main(String[] args) {
        //向下限定  说明有天花板
        ArrayList<Person> persons = new ArrayList<>();
        ArrayList<Student> students = new ArrayList<>();
        method(students);		//此时这里就可以传递这个值了
        method(persons);
        
        //向下限定
        ArrayList<Object> objects = new ArrayList<>();
        method2(persons);
        method2(students);
        method2(objects);
    }
    
    public static void method(ArrayList<? extends Person> list){    //传来的必须是Person的子类
        for (Object o : list){
            System.out.println(o);
        }
    }
    
    public static void method2(ArrayList<? super Student> list){    //传来的必须是Student的父类以上
        for (Object o : list){
            System.out.println(o);
        }
    }
}
后端
Java

评论