文章目錄
一、泛型類的由來
當類中要操作的引用數據類型不確定的時候,
早期定義Object來完成擴展
現在定義泛型來完成擴展
二、並不存在泛型類
1、如何驗證不存在泛型類
2、使用注意事項
三、泛型繼承
1、以泛型類爲父類
2、以非泛型類爲父類
3、泛型類與非泛型類在繼承時主要區別
一、泛型類的由來
當類中要操作的引用數據類型不確定的時候,
早期定義Object來完成擴展,
現在定義泛型來完成擴展。
(1)先看早期的做法,看個例子
public class GeremicClass
{
public static void main(String[] args) {
Tools u = new Tools();
//u.setObject(new Teacher()); 類型轉化異常
u.setObject(new Worker());
Worker w = (Worker)u.getObject();
}
}
class Teacher
{
}
class Worker
{
}
class Tools
{
private Object obj;
public void setObject(Object obj){
this.obj = obj;
}
public Object getObject(){
return obj;
}
}
(2) 定義泛型後的做法
public class GeremicClass {
public static void main(String[] args) {
Tools<Worker> u = new Tools<Worker>();
//u.setObject(new Teacher()); 類型轉化異常
u.setObject(new Worker());
Worker w = u.getObject();
}
}
class Tools<T>
{
private T obj;
public void setObject(T obj){
this.obj = obj;
}
public T getObject(){
return obj;
}
}
分析 : 不需要進行類型強轉。在調用setObject
方法時,如果我傳入的參數類型非Worker
類型,編譯直接報錯。而早期通過定義Object
來完成擴展,需要強轉,而且如果傳參類型出錯,只能到運行時體現。不利於定位問題。我們稱Tools
爲自定義的泛型類。
二、並不存在泛型類
這個標題不是與上面的相違背。不急。先看一個簡單的例子。
public static void main(String[] args)
{
ArrayList<Teacher> l1 = new ArrayList<Teacher>();
ArrayList<Worker> l2 = new ArrayList<Worker>();
System.out.println(l1.getClass()==l2.getClass());
}
你覺得上述代碼是輸出ture還是false呢?答案是true。
1、如何驗證不存在泛型類
不管泛型類型的實際參數是什麼,他們在運行的時候總會有相同的class,即系統並沒有生成新的class文件。 實際上,泛型對其所有可能的類型參數,都具有同樣的行爲,從而可以把相同的類當成許多不同的類來處理。
2、使用注意事項
<1> 因爲不存在泛型類,所以經過instanceof運算符處理後不能使用泛型類。
//下面的代碼編譯時會引發錯誤
if(l1 instanceof ArrayList<Teacher>)
{
}
<2> Java類中的靜態方法、靜態初始化、靜態變量聲明、初始化中不允許使用泛型參數。
三、泛型繼承
和普通類一樣,泛型類一樣支持繼承。任何一個泛型類都可以作爲父類或者子類。
1、以泛型類爲父類
當一個類的父類是泛型時,這個子類必須要把類型參數傳遞給父類,所以這個子類必定是泛型類。
// main方法
public static void main(String[] args)
{
SubTools<String> t1 = new SubTools<String>("hello java");
System.out.println(t1.getObject());
}
//定義一個泛型類
class Tools<T>
{
private T obj;
public Tools()
{
}
//當程序員提供有參構造方法,系統將不會提供無參構造方法
public Tools(T obj){
this.obj = obj;
}
public void setObject(T obj){
this.obj = obj;
}
public T getObject(){
return obj;
}
}
//泛型類的子類(注意SubTools是如何聲明稱爲Tools的子類的。格式。)
class SubTools<T> extends Tools<T>
{
public SubTools(T obj){
super(obj); //調用的是父類有參構造方法。
//super(); 調用父類無參構造方法
}
}
當然,除此之外,子類還可以擴展自己的類型參數。看下面一個例子
//泛型類的子類(注意SubTools是如何聲明稱爲Tools的子類的。格式。)
class SubTools<T,U> extends Tools<T>
{
public U extentsion;
public SubTools(T obj,U ex){
super(obj); //調用的是父類有參構造方法。
//super(); 調用父類無參構造方法
extentsion = ex;
}
public U getExtension(){
return extentsion;
}
}
//main方法如下
public static void main(String[] args) {
SubTools<String,Integer> t1 = new SubTools<String,Integer>("value is:",100);
System.out.println(t1.getObject()+t1.getExtension());
//輸出: value is:100
}
2、以非泛型類爲父類
泛型類也可以使用非泛型類作爲父類,此時不需要傳遞類型參數給父類,所有的類型參數都是爲自己準別的。
//定義一個泛型類,其父類不是泛型類
class GemericClass<T> extends Teacher{
private T obj;
public GemericClass(String name,T obj){
super(name);
this.obj = obj;
}
public T getObj(){
return obj;
}
}
// 非泛型父類
class Teacher
{
private String name;
public Teacher(){
}
public Teacher(String name){
this.name = name;
}
public String getName(){
return name;
}
}
//main方法
public static void main(String[] args) {
GemericClass<Integer> t1 = new GemericClass<Integer>("value is:",500);
System.out.println(t1.getName()+t1.getObj());
//輸出: value is:500
}
3、泛型類與非泛型類在繼承時主要區別
泛型類的子類必須將泛型父類所需要的類型參數,沿着繼承鏈向上傳遞。(類似於構造方法)