天天看點

Java_泛型一.泛型

一.泛型

1.概述

  • 可以在類或方法中預支地使用未知的類型。 可以在定義類,定義接口或者定義方法的時候使用,代表一種未知的資料類型,表示形式為<>
public class GenericDemo {
	public static void main(String[] args) {
		Collection coll = new ArrayList();
		coll.add("abc");
		list.add("hello");
		coll.add(5);//由于集合沒有做任何限定,任何類型都可以給其中存放
		Iterator it = coll.iterator();
		while(it.hasNext()){
			//需要列印每個字元串的長度,就要把疊代出來的對象轉成String類型
			String str = (String) it.next();
			System.out.println(str.length());
		}
	}
}
           
1.由于集合中什麼類型的元素都可以存儲。導緻取出時強轉引發運作時 ClassCastException。
2.Collection雖然可以存儲各種對象,但實際上通常Collection隻存儲同一類型對象。例如都是存儲字元串對象。是以在JDK5之後,新增了泛型(Generic)文法,讓你在設計API時可以指定類或方法支援泛型,這樣我們使用API的時候也變得更為簡潔,并得到了編譯時期的文法檢查。
3.一般在建立對象時,将未知的類型确定具體的類型。當沒有指定泛型時,預設類型為Object類型。

2.好處

  • 将運作時期的ClassCastException,轉移到了編譯時期變成了編譯失敗。
  • 避免了類型強轉的麻煩。
public class GenericDemo2 {
	public static void main(String[] args) {
        Collection<String> list = new ArrayList<String>();
        list.add("abc");
        list.add("hello");
        // list.add(5);//當集合明确類型後,存放類型不一緻就會編譯報錯
        // 集合已經明确具體存放的元素類型,那麼在使用疊代器的時候,疊代器也同樣會知道具體周遊元素類型
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            String str = it.next();
            //當使用Iterator<String>控制元素類型後,就不需要強轉了。擷取到的元素直接就是String類型
            System.out.println(str.length());
        }
	}
}
           

泛型是資料類型的一部分,我們将類名與泛型合并一起看做資料類型。

泛型隻能是引用資料類型

泛型一般隻和集合結合使用

3.泛型的定義與使用

3.1定義和使用含有泛型的類

  • 定義泛型類的格式
public class ArrayList<E>{ //定義了一個帶有泛型的類   E代表一種未知的資料類型
    public boolean add(E e){ }

    public E get(int index){ }
   	....
}
           
  • 使用:在建立對象時确定泛型

此時,變量E的值就是String類型,那麼我們的類型就可以了解為:

class ArrayList<String>{ 
     public boolean add(String e){ }

     public String get(int index){  }
     ...
}
           

3.2 含有泛型的方法

  • 定義格式
  • 使用格式:調用方法時,确定泛型的類型
public class MyGenericMethod {	  
    public <E> void show(E e) {
    	System.out.println(e.getClass());
    }
    
    public <E> E show2(E e) {	
    	return e;
    }
}
           
public class GenericMethodDemo {
    public static void main(String[] args) {
        // 建立對象
        MyGenericMethod mm = new MyGenericMethod();
        // 示範看方法提示
        mm.show("aaa");
        mm.show(123);
        mm.show(12.45);
    }
}
           

3.3 含有泛型的接口

  • 定義格式
public interface MyGenericInterface<E>{
	public abstract void add(E e);
	
	public abstract E getE();  
}
           
  • 使用: 定義實作類時确定泛型的資料類型
格式:
public class 實作類名 implements 接口名<具體的引用資料類型>{

}
           
public class MyImp1 implements MyGenericInterface<String> {
	@Override
    public void add(String e) {
        // 省略...
    }

	@Override
	public String getE() {
		return null;
	}
}
           
此時,泛型E的值就是String類型。
  • 定義實作類時不确定泛型的具體資料類型,直到建立對象時,确定泛型的類型
格式:
public class 實作類名<E> implements 接口名<E>{

}
           
public class MyImp2<E> implements MyGenericInterface<E> {
	@Override
	public void add(E e) {
       	 // 省略...
	}

	@Override
	public E getE() {
		return null;
	}
}
           
/*
 * 使用
 */
public class GenericInterface {
    public static void main(String[] args) {
        MyImp2<String>  my = new MyImp2<String>();  
        my.add("aa");
    }
}
           

4.泛型通配符

4.1 概述

當使用泛型類或者接口時,傳遞的資料中,泛型類型不确定,可以通過通配符<?>表示。但是一旦使用泛型的通配符後,隻能使用Object類中的共性方法,集合中元素自身方法無法使用。

4.2 基本使用

泛型的通配符:不知道使用什麼類型來接收的時候,此時可以使用?,?表示未知通配符。

此時隻能接受資料,不能往該集合中存儲資料。

public static void main(String[] args) {
    Collection<Integer> list1 = new ArrayList<Integer>();
    getElement(list1);
    Collection<String> list2 = new ArrayList<String>();
    getElement(list2);
}
public static void getElement(Collection<?> coll){}
//?代表可以接收任意類型
           
泛型不存在繼承關系 Collection<Object> list = new ArrayList<String>();這種是錯誤的
           

4.3 通配符進階使用----受限使用

之前設定泛型的時候,實際上是可以任意設定的,隻要是類就可以設定。但是在JAVA的泛型中可以指定一個泛型的上限和下限。

  • 泛型的上限:

    格式: 類型名稱 <? extends 類 > 對象名稱

    意義: 隻能接收該類型及其子類

  • 泛型的下限:

    格式: 類型名稱 <? super 類 > 對象名稱

    意義: 隻能接收該類型及其父類型

比如:現已知Object類,String 類,Number類,Integer類,其中Number是Integer的父類

public static void main(String[] args) {
    Collection<Integer> list1 = new ArrayList<Integer>();
    Collection<String> list2 = new ArrayList<String>();
    Collection<Number> list3 = new ArrayList<Number>();
    Collection<Object> list4 = new ArrayList<Object>();
    
    getElement1(list1);
    getElement1(list2);//報錯
    getElement1(list3);
    getElement1(list4);//報錯
  
    getElement2(list1);//報錯
    getElement2(list2);//報錯
    getElement2(list3);
    getElement2(list4);
  
}
// 泛型的上限:此時的泛型?,必須是Number類型或者Number類型的子類
public static void getElement1(Collection<? extends Number> coll){}
// 泛型的下限:此時的泛型?,必須是Number類型或者Number類型的父類
public static void getElement2(Collection<? super Number> coll){}