一、定义
    泛型,即“参数化类型”。就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
    例如:GenericClass<T>{} 里面的T可以随意。

方法使用泛型

public class GenericMethod {
    /*注意:泛型里面的字母可以自己随意写
    * 定义泛型方法格式为:
    * 修饰符 <泛型> 返回值类型 方法名(参数列表(使用泛型)){
    * 方法体
    * }
    * */
    public <M> void method01(M m){
        System.out.println(m);
    }

    //静态方法
    public static <s> void method02(s a){
        System.out.println(a);
    }
}
public class DemoGenericMethod {
    public static void main(String[] args) {
        GenericMethod gm = new GenericMethod();

        gm.method01(1);
        gm.method01(1.1);
        gm.method01("abc");
        System.out.println("================");
        GenericMethod.method02(2);
        GenericMethod.method02(2.1);
        GenericMethod.method02("efg");
    }


}

输出结果:

1
1.1
abc
================
2
2.1
efg

类使用泛型

GenericClass_02.java

/*
* 当不确定类型时,可以使用泛型。
* 泛型在new对象时确定,如果new对象时没有确定,默认是用的是object类型
* */
public class GenericClass_02<E> {
    public E getName() {
        return name;
    }

    public void setName(E name) {
        this.name = name;
    }

    private E name;

}

DemoGenericClass_02A.java

public class DemoGenericClass_02A {
    public static void main(String[] args) {
        GenericClass_02 obj = new GenericClass_02();
        obj.setName("字符串");
        Object name = obj.getName();//返回的也是object类型

        //可以整型
        GenericClass_02<Integer> it = new GenericClass_02<>();
        it.setName(123);
        Integer itReturn = it.getName();
        int itReturn01 = it.getName();

        //可以是字符串型
        GenericClass_02<String> str = new GenericClass_02<>();
        str.setName("abc");
        String strReturn = str.getName();

    }
}

 

二、存在的意义
    1、适用于多种数据类型执行相同的代码(代码复用)
    2、泛型中的类型在使用时指定,不需要强制类型转换(类型安全,编译器会检查类型)
三、实现
    修饰符 class 类名<代表泛型的变量> {  }
四、什么时候确定泛型
    1、在创建对象的时候确定泛型
        例如,`ArrayList<String> list = new ArrayList<String>();`
    2、调用方法时,确定泛型的类型

    3、在实现类时确定类型

GenericInterface.java

public interface GenericInterface <I>{
    public abstract  void method(I i);
}

GenericInterfaceIpl01.java

public class GenericInterfaceIpl01 implements GenericInterface <String>{
    @Override
    public void method(String s) {
        System.out.println(s);
    }

}

     4、实现类也和接口使用一样的泛型,具体类型在确定对象时确定

public class GenericInterfaceIpl02<I> implements GenericInterface<I> {
    @Override
    public void method(I i) {
        System.out.println(i);
    }
}

五、通配符

import java.util.ArrayList;
import java.util.Iterator;

/*
泛型的通配符:
?代表任意数据类型
使用方式:
不能创建对象使用
只能作为方法参数使用
* */
public class GenericClass02 {
    public static void main(String[] args) {
        ArrayList<String> str = new ArrayList<>();
        str.add("abc");
        str.add("def");

        ArrayList<Integer> it = new ArrayList<>();
        it.add(1);
        it.add(2);
        //==========
        method(str);
        //=========
        method(it);
    }

    public static void method(ArrayList<?> a){
        Iterator<?> it = a.iterator();
        while(it.hasNext())
        {
            it.next();
        }


    }


}

六、受限泛型
    在JAVA的泛型中可以指定一个泛型的**上限**和**下限**。
    1、泛型的上限:
        *  类型名称 <? extends 类 > 对象名称
        *  只能接收该类型及其子类`
    2、泛型的下限**:
        *类型名称 <? super 类 > 对象名称
        *意义: 只能接收该类型及其父类型    
六、注意事项
    1、一般在创建对象时,将未知的类型确定具体的类型。当没有指定泛型时,默认类型为Object类型。
    2、泛型不存在继承关系 Collection<Object> list = new ArrayList<String>();这种是错误的。

     3、泛型里面的字母可以自己随意写

七、举例

import java.util.ArrayList;
import java.util.Iterator;

public class ClassGeneric {
    public static void main(String[] args) {

        //不使用泛型
        methodNoGeneric();
        //使用泛型
        methodGeneric();
    }

    /*
    * 不使用泛型:
    * 优点:
    * 1、可以存放任何类型对象
    * 缺点:
    * 1、不安全会引发异常
    * */
    private static void methodNoGeneric() {
        ArrayList arry = new ArrayList();
        arry.add("abc");
        arry.add(1);

        Iterator it = arry.iterator();
        while(it.hasNext()){
            Object obj = it.next();
            //没有是使用泛型,如果要获取长度,需要向下转换
            String str = (String) obj; //这里存在一个问题,如果某个obj存放的不是String,
            // 运行时会抛出错误ClassCastException
            System.out.println(str+"长度是:"+str.length());
        }
    }

    /*
    * 使用泛型的优点:
    * 1、避免了类型转换的麻烦,存储期是什么类型,取时就自动是什么类型
    * 2、将运行期的错误,提升到编译器
    * 缺点:
    * 1、使用什么泛型,就只能存储什么泛型。
    * */
    public static void methodGeneric(){
        ArrayList<String> arry1 = new ArrayList<>();
        arry1.add("abc");
        arry1.add("def");

        Iterator<String> it = arry1.iterator();
        while(it.hasNext()){
            String st =it.next();
            System.out.println(st + "长度是:"+st.length());
        }

    }
}