首頁  >  文章  >  Java  >  Java 泛型與包裝類別範例分析

Java 泛型與包裝類別範例分析

王林
王林轉載
2023-04-21 19:19:06760瀏覽

1、什麼是泛型

泛型的本質是為了參數化類型(在不創建新的類型的情況下,透過泛型指定的不同類型來控制形參具體限制的類型)。

先看以下的例子:

我們以前學過的數組,只能存放指定類型的元素。如:int[] array=new int[10];String[] array=new String[10];而Object類別是所有類別的父類,那麼我們是否可以建立Obj陣列呢?

class Myarray{
    public Object[] array=new Object[10];
    public void setVal(int pos,Object val){
        this.array[pos]=val;
    }
    public Object getPos(int pos){
        return this.array[pos];
    }
}
public class TestDemo{
    public static void main(String[] args) {
        Myarray myarray=new Myarray();
        myarray.setVal(1,0);
        myarray.setVal(2,"shduie");//字符串也可以存放
        String ret=(String)myarray.getPos(2);//虽然我们知道它是字符串类型,但是还是要强制类型转换
        System.out.println(ret);
    }
}

以上程式碼實作後,我們發現:

  • 任何類型的資料都能存放

  • 2號下標本來就是字串,但是必須進行強制型別轉換

以此引出泛型,泛型的目的是:指定目前的容器要持有什麼類型的對象,讓編譯器自己去檢查。

2、泛型的語法

class 泛型類別名稱d9a850d276535a6ae003bca4dfab1b3b{

  //這裡可以使用型別參數

}

泛型的使用:

泛型類別03354cf2845c31f37c08275aed8db581 變數名稱=new 泛型類別03354cf2845c31f37c08275aed8db581(建構方法實參)

MyArray  list=new MyArraya8093152e673feb7aba1828c43532094();

【註】

  • #型別後的a8093152e673feb7aba1828c43532094代表佔位符,表示目前類別是泛型類別

  • 在實例化泛型時,a8093152e673feb7aba1828c43532094中不能是簡單的類型,需要是包裝類別

  • a8093152e673feb7aba1828c43532094不參與泛型的型別組成

  • 不能new泛型的陣列

  • 使用泛型不需要進行強制型別轉換

#一個簡單的泛型:

//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
//在实例化泛型类时,必须指定T的具体类型
public class Test<T>{ 
    //key这个成员变量的类型为T,T的类型由外部指定  
   private T key;
 
    public Test(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定
        this.key = key;
    }
 
    public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
        return key;
    }
}

擦除機制:編譯時會將a8093152e673feb7aba1828c43532094中的型別擦除掉,所以a8093152e673feb7aba1828c43532094中的東西不參與類型的組成。會將T擦除為Object。

為什麼不能實例化泛型類型的陣列?

陣列和泛型之間的一個重要區別是它們如何強制執行類型檢查。數組在運行時儲存和檢查類型信息,而泛型是在編譯時檢查類型錯誤。

傳回的Object數組裡面,可能存放著任何類型的數據,如string,透過int類型的數組來接收,編譯器認為是不安全的。

3、泛型的上界

語法:

class 泛型類別名稱3c77d6081ac41fcac8a1ee971a62484e{

# }

範例:

public class MyArray{} //E只能是Number或Number的子類別

public class MyArray587c6b841f9775ac09a42ccb3bfcf6bc>{}

//E一定實作了Comparable介面的類別

##【註】沒有指定邊界的E,可以看作E extends Object

4、萬用字元

?用於在泛型的使用,即為通配符。通配符用來解決反泛型無法協變的問題。

如下兩段程式碼:

代码一:
public static<T> void printList1(ArrayList<T> list){
   for(T x:list){
      System.out.println(x);
   }
}
 
代码二:
public static<T> void printList2(ArrayList<?> list){
   for(Object x:list){
      System.out.println(x);
   }
}

程式碼2中使用了通配符,和程式碼1相比,此時傳入程式碼1的具體是什麼資料類型,我們是不清楚的。

(1)通配符的上界

語法:

17c0f368e92dd93822c5c4ac304197ad //可以傳入的實參類型為Number或Number的子類別

範例:對於以下關係,我們需要寫一個方法來列印儲存了Animal或Animal子類別的list。

Animal

Cat extends Animal
Dog extends Animal

程式碼一:

public static <t extends Animal> void print1(List<T> list>{
    for(T animal:list){
        System.out.println(animal);//调用了T的toString
    }
}

此時T型別是Animal的子類或自己。

程式碼二:透過通配符實作

public static void print2(List<? extends Animal> list){
    for(Animal animal:list){
       Syatem.out.println(animal);//调用了子类的toString方法
    }
}

兩種程式碼的差異:

  • #對於泛型實作的方法來說,370684dcd157e96b03c92635015a5aca對T進行了限制,只能是Animal的子類別。傳入Cat,就是Cat。

  • 對於通配符實作的方法來說,相當於對Animal進行了規定,允許傳入Animal的子類別。具體哪個子類,此時並不清楚。如:傳入Cat,實際上宣告的類型是Animal,使用多態才能呼叫Cat的toString方法

通配符上界→父子類別關係:

#//需要使用通配符來確定父子類型

MyArrayLista2b037db85f4e1df0e812b9647ac55a8是MyArrayListc0f559cc8d56b43654fcbe4aa9df7b4a或MyArrayListeafb63d086dd6c9bd19609d76bcc2869的父類別

##MyArrayList<?> ;? extends Number>的父類別

 ArrayList<Integer> arrayList1 = new ArrayList<>();
 ArrayList<Double> arrayList2 = new ArrayList<>();
 List<? extends Number> list = arrayList1;
 //list.add(1,1);//报错,此时list的引用的子类对象有很多,再添加的时候,任何子类型都可以,为了安全,java不让这样进行添加操作。
 Number a = list.get(0);//可以通过
 Integer i = list.get(0);//编译错误,只能确定是Number子类

【註】

    不能加,list中儲存的可能是Number也可能是Number的子類,無法確定類型。
  • 通配符上界適合讀取,不適合寫入。
  • (2)通配符的下界

語法:

fd46123a03593e01309cb2d3eaa46238

6a4551997e2af77c2331ddf9cfbb1e38//可以傳入的參數型別是Integer或Integer的父類別

通配符下界的父子類別關係:

MyArrayList474555482eb79f9e4e676a9012437c1d是MyArrayList1c0477c859e3a4cbd4faa63087d62a35的父类类型

MyArrayLista10469e4b40f04339ce5bebfbf5abb4c是MyArrayList474555482eb79f9e4e676a9012437c1d的父类

通配符下界适合写入元素,不适合读取。

5、包装类

在Java中,由于基本类型不是继承自Object,为了在泛型中可以支持基本类型,每个基本类型都对应了一个包装类。除了Integer和Character,其余基本类型的包装类都是首字母大写。

拆箱和装箱:

int i=10;
 
//装箱操作,新建一个Integer类型对象,将i的值放入对象的某个属性中
Integer ii=i;  //自动装箱
//Integer ii=Integer.valueOf(i);
Integer ij= new Integer(i);//显示装箱
 
//拆箱操作,将Integer对象中的值取出,放到一个基本数据类型中
int j=ii.intValue();//显示的拆箱
int jj=ii;//隐式的拆箱

以上是Java 泛型與包裝類別範例分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除