JavaSE--泛型

1)泛型是什麼:

是一種未知的數據類型,當我們不知道使用什麼數據類型時,可以使用泛型。
泛型也可以看作是一個變量,用來接收數據類型。
E e:Element 元素
T t:Type 類型

2)使用泛型解決的問題:

解決向下轉型帶來的類轉換異常(ClassCastException)。

3)使用泛型的好處:

●避免了類轉換的麻煩,存儲的是什麼類型,取出的就是什麼類型。
●把運行期異常提升到了編譯期異常。
弊端:不使用泛型時能存儲任意類型的數據。(不適用默認則爲Object)

public class Test {
    public static void main(String[] args) {
//        show1();
        show2();
    }
        //不使用泛型
        public static void show1() {
            //數組不適用泛型則爲默認類型,爲Object
            ArrayList list = new ArrayList();
            list.add(1);
            list.add("abc");
            //迭代輸出
            Iterator it = list.iterator();
            while (it.hasNext()){
                Object obj = it.next();
                System.out.println(obj);
                //調用String特有的方法,Length獲取長度
                //向下轉型,會拋出異常,不能把Integer類型轉換爲String類型
                String s =(String) obj ;
                System.out.println(s.length());
            }
    }
        //使用泛型
        public static void show2(){
            ArrayList<String> list =new ArrayList<>();
            list.add("Aaa");
            list.add("Bbb");
            list.add("Ccc");
            //list.add(123); 報錯
            //迭代輸出
            for (String str : list){
                System.out.println(str);
            }
        }
}

4)含有泛型的類:

使用泛型後,所有類中屬性的類型都是動態設置。即創建對象時是什麼類型,泛型就是什麼類型。

//含有泛型的類
public class GenericClass <E> {
    public E name;
    public E getName() {
        return name;
    }
    public void setName(E name) {
        this.name = name;
    }
}
public class doMain {
    public static void main(String[] args) {
        GenericClass<String> gc1 = new GenericClass<>();
        gc1.setName("String類型");

        GenericClass<Integer> gc2 = new GenericClass<>();
        gc2.setName(1);
    }
}

如果不使用泛型,我們就只能使用一種數據類型。(Object除外,使用Object則會帶來安全隱患問題)

5)含有泛型的方法:

定義在方法的修飾符和返回值之間。
作用:調用方法時,傳遞什麼類型,泛型就是什麼類型。
格式:

修飾符 <泛型> 返回值類型 方法名(參數列表(使用泛型)){
	方法體;
	}
public class GenericMethod {
    //含有泛型的方法
    public <T> void method(T t){
        System.out.println(t);
    }
    //含有泛型的靜態方法
    public static <S> void method2(S s){
        System.out.println(s);
    }
}
public class doMain {
    public static void main(String[] args) {

        GenericMethod gm = new GenericMethod();
        gm.method(10);
        gm.method("abc");
        gm.method(13);

        GenericMethod.method2("靜態方法");
        GenericMethod.method2("2");
    }
}

6)含有泛型的接口:

//含有泛型的接口
interface IGeneric<I> {
    public abstract void method(I i);
}

實現方式一:

實現類繼續設置泛型標記。

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

實現方式二:

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

一和二的差別:
有沒有爲子類設置具體的泛型。

public class doMain {
    public static void main(String[] args) {
        IGenericImpl gil = new IGenericImpl();
        gil.method("使用泛型接口的實現類1");
        gil.method(1);

        IGenericImpl2 gil2 = new IGenericImpl2();
        gil2.method("使用泛型接口的實現類2");
    }
}

7)泛型的通配符:

<?>

解決的是參數傳遞的問題。
只能夠接收數據,不能夠存儲數據。

public class Generic {
    public static void main(String[] args) {
        ArrayList<Integer> list01 =new ArrayList<>();
        list01.add(1);
        list01.add(2);

        ArrayList<String> list02 = new ArrayList<>();
        list02.add("a");
        list02.add("b");

        printArray(list01);
        printArray(list02);

        //它只能夠接收數據,不能夠存儲數據
        //ArrayList<?> list03 = new ArrayList<?>();報錯
    }
    //定義一個方法,能遍歷所有類型的ArrayList集合。
    //這時候我們不知道ArrayList集合使用什麼數據類型,可以用泛型的通配符 ? 來接收數據類型
//    public static void printArray(ArrayList<String> list){
    public static void printArray(ArrayList<?> list){
        Iterator<?> it = list.iterator();
        while (it.hasNext()){
            Object obj =it.next();
            System.out.println(obj);
        }
    }
}

注意:在明確設置一個類爲泛型類型時,沒有繼承關係的概念。

public static void printArray(ArrayList<String> list){
public static void printArray(ArrayList<Object> list){

雖然Object與String類是父子類的關係,但換到泛型中就屬於兩個完全獨立的概念。

通配符的高級使用——受限泛型

●泛型的上限:
格式:類名 <? extends 類 > 對象名,可以在方法聲明和參數上使用。
作用:只能夠接收該類型及其子類。

●泛型的下限:
格式:類名 <? super 類 > 對象名,可以在方法參數上使用。
作用:只能夠接收該類型及其父類。

public class doMain {
    public static void main(String[] args) {
        Collection<Integer> list1 = new ArrayList<>();
        Collection<String> list2 = new ArrayList<>();
        Collection<Number> list3 = new ArrayList<>();
        Collection<Object> list4 = new ArrayList<>();

        getElement1(list1);
        getElement1(list2);//報錯
        getElement1(list3);
        getElement1(list4);//報錯

        getElement2(list1);//報錯
        getElement2(list2);//報錯
        getElement2(list3);
        getElement2(list4);
    }

    //泛型的上限:此時的泛型?,必須是Number類或其類型的子類
    public static void getElement1(Collection<? extends Number> coll){}
    //泛型的下限:此時的泛型?,必須是Number類或其類型的父類
    public static void getElement2(Collection<? super Number> coll){}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章