参数类型 或者 类型参数化
在不创建新的类型的情况瞎,通过泛型指定的不同类型来控制形参具体限制的类型
    public static void main(String[] args) {
        //限定类型的的集合使用
        ArrayList<String> list = new ArrayList<>();
        list.add("123");
        list.add("456");
        list.add("789");
        list.add("abc");
        list.forEach(val -> System.out.println(val.getClass().getTypeName()));
        //不限制类型转换的集合
        ArrayList list2 = new ArrayList();
        list2.add(1);
        list2.add("2");
        list2.add(3);
        list2.add("4");
        list2.forEach(val -> System.out.println(val.getClass().getTypeName()));

    }



java.lang.String
java.lang.String
java.lang.String
java.lang.String

java.lang.Integer
java.lang.String
java.lang.Integer
java.lang.String

泛型运用的意义:

编译期间确定类型,保证类型安全;
避免强制转换的逻辑;
提高代码的重用率,增加程序的通用灵活性;

泛型类型擦除:

泛型只在编译阶段有效,泛型类型在逻辑上可看成是多个不同的类型,但是其实质 都是同一个数据类型
编译之后程序会采取去泛型化的措施
    public static void demo2() {
        //限定类型的的集合使用
        ArrayList<String> list = new ArrayList<>();
        //不限制类型转换的集合
        ArrayList list2 = new ArrayList();
        System.out.println(list.getClass());
        System.out.println(list2.getClass());
        System.out.println(list.getClass() ==list2.getClass());
    }
    class java.util.ArrayList
    class java.util.ArrayList
    true

    /**
     * 对限定了形参类型集合进行反射操作
     */
    public static void demo3 () throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //限定类型的的集合使用
        ArrayList<String> list = new ArrayList<>();
        list.add("123");
        list.add("456");
        list.add("789");
        list.add("abc");
        System.out.println("原存储长度:"+list.size());
        System.out.print("原元素类型:\n");
        list.forEach(val -> System.out.print(val.getClass().getTypeName()+" \n"));
        System.out.println("=================");
        //进行反射 调用add
        Class clazz = list.getClass();
        Method method = clazz.getDeclaredMethod("add",Object.class);
        method.invoke(list,1000);
        //非泛型集合遍历会报ClassCastException
        System.out.println("反射后的存储长度:"+list.size());
        System.out.println("=================");
    }

    原存储长度:4
    原元素类型:
    java.lang.String 
    java.lang.String 
    java.lang.String 
    java.lang.String 
    =================
    反射后的存储长度:5
    =================

泛型的通配符表达式:

无边界通配符 ? <?>  传递的形参 ? 可以使任意类型
上界通配符 <? extends E> 限制传递形参 ? 的上限为E
下界通配符 <? super E>  限制传递形参 ? 最低为E
    public static void main(String[] args){
        //demo1();
        //demo2();
        //demo3();
        //demo4  可以传递任意形参的list集合
        ArrayList<String> list = new ArrayList<>();
        ArrayList<Integer> list2 = new ArrayList<>();
        ArrayList<DemoBean> list3 = new ArrayList<>();
        demo4(list);
        demo4(list2);
        demo4(list3);
        //demo5 要求必须是 Number 或 Number以下的形参集合
        ArrayList<Number> list4 = new ArrayList<>();
        ArrayList<Integer> list5 = new ArrayList<>();
        ArrayList<Double> list6 = new ArrayList<>();
        ArrayList<String> list7 = new ArrayList<>();
        demo5(list4);
        demo5(list5);
        demo5(list6);
        //类型为String的集合就不可以传入 因为不是Number或Number以下的形参
        //demo5(list7);

        //demo6 要求必须是 Integer 或 Integer以上的形参
        ArrayList<Number> list8 = new ArrayList<>();
        ArrayList<Integer> list9 = new ArrayList<>();
        ArrayList<Object> list10 = new ArrayList<>();
        ArrayList<Double> list11 = new ArrayList<>();
        ArrayList<String> list12 = new ArrayList<>();
        demo6(list8);
        demo6(list9);
        demo6(list10);
        //Double在下一级 不能传入
        //demo6(list11);
        //String 与 Integer没有上下联系 不能传入
        //demo6(list12);

    }

/**
     * 无边界通配符
     * 无边界通配符 ? <?>
     */
    public static void demo4 (ArrayList<?> list){
        for (int i = 0; i <= list.size();i++){
            System.out.println(list.get(i));
        }
    }
    /**
     * 上界通配符 <? extends E>
     *
     */
    public static void demo5 (ArrayList<? extends Number> list){
        for (int i = 0; i <= list.size();i++){
            System.out.println(list.get(i));
        }
    }
    /**
     下界通配符 <? super E>
     */
    public static void demo6 (ArrayList<? super Integer> list){
        for (int i = 0; i <= list.size();i++){
            System.out.println(list.get(i));
        }
    }

泛型方法:

实体方法:
实体方法可以使用类中定义的泛型和方法中定义的类型
静态方法:
静态方法不可以使用类中定义的泛型只可以使用静态方法中定义的泛型
public class DemoBean1<A,B> {
    private A a;
    private B b;

    public DemoBean1(A a, B b) {
        this.a = a;
        this.b = b;
    }
    //可以调用传入类定义的泛型A
    public A method1(A a){
        return a;
    }
    //方法中定义了一个泛型 E 传入E 返回的是类定义的泛型B
    public <E> B method2(E e){
        return b;
    }
    //该静态方法定义了一个泛型 F 可以调用该方法定义的F 但不能调用类所定义的泛型 A B
    public static <F> F staticMethod1(F f){
        return f;
    }

}

泛型接口:

/**
 * 
 * 泛型接口
 * 实现更具有灵活性
 */
public interface DemoInterface<V> {
    public V add();
    public V sub();
    public V mul();
    public V div();
}

//实现类

public class DemoInterFaceBean implements DemoInterface<Integer>{
    @Override
    public Integer add(Integer val, Integer val2) {
        return val+val2;
    }

    @Override
    public Integer sub(Integer val, Integer val2) {
        return val-val2;
    }

    @Override
    public Integer mul(Integer val, Integer val2) {
        return val*val2;
    }

    @Override
    public Integer div(Integer val, Integer val2) {
        return val/val2;
    }
}


public class DemoInterFaceBean1 implements DemoInterface<Double>{
    @Override
    public Double add(Double val, Double val2) {
        return val+val2;
    }

    @Override
    public Double sub(Double val, Double val2) {
        return val-val2;
    }

    @Override
    public Double mul(Double val, Double val2) {
        return val*val2;
    }

    @Override
    public Double div(Double val, Double val2) {
        return val/val2;
    }
}

泛型的使用:

先声明.在使用;
声明采用<>方式
声明一般约定采用单个大写字母表示,如、等

泛型类: ​ import lombok.Data; /** * Created by 于占峰 on 2020/3/27/027. */ @Data public class DemoBean2<V> { private V value; public DemoBean2(V value) { this.value = value; } public DemoBean2() { } public static void main(String[] args) { //实例化类的传入类定义泛型的具体类型 DemoBean2<String> demoBean = new DemoBean2<String>(); DemoBean2<String> demoBean1 = new DemoBean2<String>("DemoBean"); DemoBean2<Integer> demoBean2 = new DemoBean2<Integer>(8888); System.out.println(demoBean); System.out.println(demoBean1); } DemoBean2(value=null) DemoBean2(value=DemoBean) DemoBean2(value=8888)