Java學習筆記(泛型)

來源:互聯網
上載者:User

泛型是一種代碼級的有效複用手段,理解泛型的機制有利於更好的編寫程式.

1) 泛型類
package generictest;

public class MyA {

public MyA()
{

}
public String Name;
public String ReturnName()
{
return Name+"hello";
}
}
package generictest;

public class MyB extends MyA implements MyInterface {
public MyB()
{

}

@Override
public String getXXXXName() {
// TODO Auto-generated method stub
return "From interface:"+this.Name;
}
}
package generictest;

public interface MyInterface {
   public String getXXXXName();
}
package generictest;

import java.util.LinkedList;
import java.util.List;
import java.lang.reflect.*;
import java.lang.*;

public class MyGeneric<T extends MyA & MyInterface>
{
public LinkedList<T> objs = new LinkedList<T>();
public void AddT(T obj)
{
objs.add(obj);
}
//如果需要執行個體化參數類型,需要傳遞類型別參數.
public void AddT(String Name,Class<T> c) throws InstantiationException, IllegalAccessException
{
    T obj=null;
    //無法轉換,編譯通過,但會有錯誤
//Class<T> theC = (Class<T>) obj.getClass();
//T theO2 = theC.newInstance();
    T theO2 = c.newInstance();
    theO2.Name = Name;
    System.out.println(theO2.getXXXXName());
AddT(theO2);
//
System.out.println(theO2.ReturnName());
}

}

2) 泛型方法及測試

package generictest;import java.util.LinkedList;public class GenericTest {public static  void main(String args[]){MyGeneric<MyB> theGeneric = new MyGeneric<MyB>();try {theGeneric.AddT("ABC1",MyB.class);theGeneric.AddT("ABC2",MyB.class);theGeneric.AddT("ABC3",MyB.class);LinkedList<MyB> theObjs = theGeneric.objs;for(MyB theB : theObjs){System.out.println(theB.Name);}} catch (InstantiationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();}//下面語句有錯,因為MyA不符合約束//MyGeneric<MyA> theGeneric2 = new MyGeneric<MyA>();System.out.println("");}//泛型方法public static <U extends MyA> U BuildInstance(Class<U> C){try {return C.newInstance();} catch (InstantiationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();}return null;}}

總結:
1) 泛型的約束不是必須的,但如果有類約束,類約束只能有一個,而且必須放在約束的第1位;
2)如果需要對泛型執行個體化,需要使用Class<T>參數明確傳遞到需要執行個體化的地方,而不能像後面語句那樣直接執行個體化:T theT=new T();
    這點上C#比較方便,只要泛型型別加上new()約束即可像執行個體化一般類那樣對泛型型別執行個體化.T theT = new T();
3)<U<T>> 不合法,即泛型型別不能作為泛型型別;(在C#中是允許的)
4) 不能建立泛型數組(在C# 中是允許的)
    MyGeneric<U>[] theA = new MyGeneric<U>[5];//是錯誤的寫法.
5)泛型型別不能是基本類型,必須是類類型(繼承於Object)(在C# 中是允許的)
    MyGeneric<int> theA = new MyGeneric<int>();//是錯誤的寫法.
6)泛類型並不能用instanceof測試來判斷類型(在C# 中是允許的)
7)泛型型別不能用於異常捕獲和異常拋出,也即如果泛型是異常類Exception的子類,並不能進行捕獲和拋出.(在C# 中是允許的)
8)泛型型別不能出現在靜態方法中.(在C# 中是允許的)
public class Singleton<T>
{
public static T getSingleInstance() // 錯誤
{
if (singleInstance == null) construct new instance of T
return singleInstance;
}
private static T singleInstance; //錯誤
}

9)泛型型別允許繼承,但必須滿足約束條件強化,即子類的約束條件不能弱於父類的約束條件.
public class MyGeneric2<T extends MyA & MyInterface & Runnable> extends MyGeneric<T> {
 } 是合法的,但public class MyGeneric2<T extends MyA> extends MyGeneric<T> {
 }是不合法的.
10) 如果B是A的子類,但MyGeneric2<B>和MyGeneric2<A>並無繼承關係,是完全不同的兩種類型.
11)泛型中使用萬用字元跟使用一般類型還是有區別的.(這種方式在C#中沒有,也沒必要)

Java的泛型機制和C#的泛型機制還是不一樣的,C#的泛型機制更多的是模板作用,而Java的泛型採用的是底層替換的方式,本質上底層的泛型型別中的類型還是被替換成了Object,

只是幫你在做Cast而已.在運行時泛型類的類執行個體只有一份,而C# 中會根據不同的型別參數來執行個體化類執行個體,下面的測試可以證明:

public class GenericTest1<T> {public static int Count=0;//無論T為何類型,Count變數只有一份,說明泛型類只有一個類執行個體.public GenericTest1(){     Count++;     System.out.println(this.Count);}public String T2String(T c){Count++;System.out.println(this.Count);return c.getClass().toString();}}

 

public class GenericTest {  public static void main(String args[])  {   //定義型別參數為Integer泛型執行個體   GenericTest1<Integer> theInt = new GenericTest1<Integer>(); //輸出theInt的類型為GenericTest1   System.out.println(theInt.getClass());   Integer theIntC= new Integer(1);   System.out.println(theInt.T2String(theIntC));   //可以如下調用,說明泛型類屬於共用性質,而非模板性質.   System.out.println( GenericTest1.Count);      GenericTest1<GenericTest> theGenericTest = new GenericTest1<GenericTest>();   //輸出theGenericTest的類型為GenericTest1   System.out.println(theGenericTest.getClass());   GenericTest theTest = new GenericTest();   System.out.println(theGenericTest.T2String(theTest)); //可以如下調用,說明泛型類屬於共用性質,而非模板性質.   System.out.println( GenericTest1.Count);  }}

從測試結果可以看出,Java的泛型和C#的泛型存在著本質上的區別,對於Java而言,無論型別參數是什麼,其泛型類的類類型(例子中都為GenericTest1)都是一樣的,類成員都是共用的,理解這點還是非常有用(Java中泛型做類型測試(instanceof)沒有意義的根本原因).Java這樣做的目的是為了向下相容.而C#經常重構.當然,這無關兩種處理方式的好壞,目的就是為了更好的利用這些特性.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.