java基礎_10_泛型

泛型

JDK1.5版本以後出現的新特性,用於解決安全問題,是一個類型安全機制。

 

好處:

1,將運行時期出現問題ClassCastException 異常 轉移到了編譯時期

   方便於程序員解決問題,讓運行時間問題減少,安全

2,避免了在重寫比較器時的強制轉換麻煩

 

泛型格式:

通過 < > 來定義要操作的引用數據類型。

 

泛型的限定:

 通配符,也可以理解爲佔位符。

 

? extends E  可以接收 及其子類。 稱上限。

? super E    可以接收 及其父類。 稱下限。

 

注意:像這種 ArrayList <Person>  al3 = new ArrayList <Student> ();

泛型裏兩邊不一樣是不是行的。必須是要一樣的,子父類也不行。

 

泛型裏的類型必須是引用類型,不能是基本數據類型,否則報錯。

例:

public void method4(ArrayList < ? extends Person >  al) //此方法只能接收Person及其子類

{

  Iterator < ? extends Person>  it = al.iterator(); //迭代的時候也要加上泛型

  while (it.hasNext())

  {

     System.out.println(it.next().getName());

  }

}

 

public void method3(ArrayList< ? super Student> al) //此方法能接收Student及其父類

{

  Iterator< ? super Student>  it = al.iterator();

  while (it.hasNext())

 {

   System.out.println(it.next());

 }

}

 

public < T > void method2(ArrayList< T > al) //此方法可以適用於所有類型的ArrayList集合

{

  Iterator < T >  it = al.iterator();

  while (it.hasNext())

  {

    T t = it.next();  //好處是可以在此處控制

    System.out.println(t);

  }

}

 

public void method(ArrayList< ? >  al)  //此方法可以適用於所有ArrayList類型的集合

{

   Iterator < ? >  it = al.iterator();

   while (it.hasNext())

   {

     System.out.println(it.next());

   }

}

 

在使用java提供的對象時,什麼時候寫泛型呢?

 

通常在集合框架中很常見,只要見到 < > 就要定義泛型。

當使用集合時,將集合中要存儲的數據類型作爲參數傳遞到 < > 中即可。

 

其實 < > 就是用來接收類型的。

 

泛型類

泛型類定義的泛型,在整個類中有效,

如果被方法使用,那麼泛型類的對象明確要操作的具體類型後,所有要操作的類型就已經固定了

 

      爲了讓方法可以操作不同類型,可以將泛型定義在方法上

 

特殊之處:

靜態方法不可以訪問類上定義的泛型。

如果想讓靜態方法操作不確定的應用數據類型,可以將泛型定義在靜態方法上。 

 :

class Demo < T >

{

   public void show( T  t)

   {

     System.out.println("show:"+t);

   }

   public < T > void print( T t)

   {

      System.out.println("print:"+t);

   }

   public static < T > void method( T t)  //注意:泛型放在返回類型前面

   {

      System.out.println("static :"+t);

   }

}

建立對象如:Demo<String> d = new Demo<String>();

 

泛型定義在接口上

例:

    // 1,類實現泛型接口
    interface Inter < T >
    {
    	void show( T t);
    }
    class Inter2 implements Inter <String>  //在實現該接口的時候指明類型
    {
         public void show(String s)
    	   { 
    		System.out.println("show:"+s);
    	   }  
    }
    // 建立對象
    Inter2 i2 = new Inter2();
	
       // 2,泛型類實現泛型接口
       class InterImpl  < T >  implements Inter < T >
       {
	  public void show( T t)
	  {
	     System.out.println("InterImp<>+show:"+t);
	  }
        }
	
    // 建立對象
    InterImpl  < Integer >  al = new InterImpl < Integer > ();
    
    // 輸出該集合元素
    Iterator < Integer >  it = al.iterator();  //迭代器也要帶上泛型
    while (it.hasNext())
    {
        System.out.println(it.next().getName());
    }

 

通過反射來獲取泛型的實際類型

如:Vector < Date >  v1  =  new Vector < Date >();

 

怎麼拿到Date這個實際類型呢? 

把它轉換成方法的參數就可以拿到,因爲在編譯的時候會去泛型化。

注意:

public void apply( Vector < Date >  v1)   {   }

                public void apply( Vector < String >  v1)  {   }

          這兩種方法不是重載,編譯不通過,因爲它們是同一方法。因爲會去泛型化,編譯會去掉泛 型的限定

 

所以通過這點,我們就可以通過方法來獲取泛型實際類型。

例:

  class Text{
    public void apply( Vector < Date >  v1)   {   }
    //通過字節碼拿到方法
    Method  applyMethod = Text.class.getMethod(“apply” , Vector.class );
    
     //通過方法返回方法的形參類型保存至數組中
    Type []  types = applyMethod.getParameterTypes();
    
    //參數化類型,因爲參數只有一個,我們取第一個元素即可。
    ParameterizedType pType = (ParameterizedType)types[0]; 
    
    //返回該參數的實際類型,因爲參數類型也可能是多個(如:Map泛型有兩個),所以這取第一個。
    System.out.println( pType.getActualTypeArguments()[0] );
    
  }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章