一文詳解Java中的包裝類和泛型
前言
在Java中,由于基本類型不是繼承?Object,為了在泛型中可以?持基本類型,Java給每個基本類型都對應(yīng)了?個包裝類型,有些情況下只有接收泛型才可以完成其功能
包裝類
| 基本數(shù)據(jù)類型 | 包裝類 |
|---|---|
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
| char | Character |
| boolean | Boolean |
這里的除了int 和char 類型的包裝類是Integer和Character 其他的都是其首字母大寫
裝箱和拆箱
public class Test {
public static void main(String[] args) {
int a = 10;
//裝箱操作 將a的值放入包裝類型中
Integer a1 = Integer.valueOf(a);
Integer a2 = new Integer(a);
//拆箱,將其包裝類型的數(shù)據(jù)放入基本數(shù)據(jù)類型中
int i = a1.intValue();
int j = a2.intValue();
System.out.println(a1);
System.out.println(a2);
System.out.println(i);
System.out.println(j);
}
}
運行結(jié)果如下

上面我們在裝箱和拆箱的時候,都要利用其官方的方法,這樣導(dǎo)致代碼量增多
自動裝箱和拆箱
public class Test {
public static void main(String[] args) {
int a = 10;
Integer a1 = (Integer) a;//強制類型轉(zhuǎn)換
Integer a2 = a;//自動類型轉(zhuǎn)換
int a3 = a1;//自動類型轉(zhuǎn)換
int a4 = (int) a2;//強制類型轉(zhuǎn)換
System.out.println(a1);
System.out.println(a2);
System.out.println(a3);
System.out.println(a4);
}
}
這里可以強制類型轉(zhuǎn)換,也可以自動類型轉(zhuǎn)換,Java是提供了這個機制
運行結(jié)果如下

基本類型和包裝類型其實并不完全相同
public class Test {
public static void main(String[] args) {
Integer a1 = 10;
Integer a2 = 10;
Integer a3 = 128;
Integer a4 = 128;
System.out.println(a1==a2);
System.out.println(a3==a4);
}
}
運行結(jié)果如下

這里是自動調(diào)用其Integer.valueOf方法
這里如果換成普通數(shù)據(jù)類型這里就相同了,就輸出兩個true,但是換成包裝類型,這里的結(jié)果就變了,為什么呢,這就要看看其包裝類型的存儲了

因為這里的傳入值如果為[-128,127]放其給定好的數(shù)組中,反之則new一個新對象,所以這里超過其這個范圍兩個地址不相同了,所以這里的127返回true,128返回false
泛型
泛型的概念
以前在寫方法的時候,都是使用的基本類型,這樣此方法只可以用于這一種類型,那可不可以創(chuàng)建一個方法可以讓多種數(shù)據(jù)類型都可以使用呢,這就引入了泛型,就是其可以使用多種類型
我們可以先自己定義一個數(shù)組可以存放多種類型的數(shù)據(jù),里面有存放和獲取一個下標(biāo)數(shù)值
class MyArray{
public Object[] array = new Object[10];
public Object getval(int index){
return array[index];
}
public void setval(int index,int val){
this.array[index] = val;
}
}
public class Test {
public static void main(String[] args) {
MyArray myArray = new MyArray();
myArray.setval(0,1);
System.out.println(myArray.getval(0));
}
}
運行結(jié)果如下

但是要注意創(chuàng)建一個對象以后,添加了一種類型的數(shù)據(jù),就不可以在添加另外一種數(shù)據(jù)了
一個數(shù)組中的元素類型要一致

就像上面已經(jīng)添加了int類型就說明這里是int類型數(shù)組,因此不可以在添加其他數(shù)據(jù)類型,這里如果在添加String類型就會出錯
泛型的使用
定義一個泛型類
class 泛型類名稱<類型形參列表> {
} // 這?可以使?類型參數(shù)
也可以放多種類型
class ClassName<T1, T2, …, Tn> {
}
這個泛型方法的使用
泛型類<類型實參> 變量名= new 泛型類<類型實參>(構(gòu)造?法實參);
//定義一個泛型類引用,并實例化一個對象
例如
ArrayList< Integer > list = new ArrayList<>();//實例化一個Integer數(shù)據(jù)類型的列表
這里在實例化的時候<>內(nèi)不用在寫是什么類型,編譯器會從前面推導(dǎo)出來
有了這個上面的代碼就可以改為
class MyArray<T>{
public Object[] array = new Object[10];
public T getval(int index){
return (T)array[index];
}
public void setval(int index,int val){
this.array[index] = val;
}
}
public class Test {
public static void main(String[] args) {
//這里指定了是Integer包裝類型的數(shù)組
//就不可以存儲其以外的數(shù)據(jù)了
MyArray<Integer> myArray = new MyArray();
myArray.setval(0,1);
//myArray.setval(1,"124");
System.out.println(myArray.getval(0));
}
}
這里在創(chuàng)建對象的時候就確定了是什么數(shù)據(jù)類型的數(shù)組
并且這里的數(shù)組數(shù)據(jù)類型只可以是包裝類型
1.如果寫成普通數(shù)據(jù)類型就會報錯,這里需要的是包裝類型

2.確定了數(shù)據(jù)類型就不可以存放其他數(shù)據(jù)類型了

交換的泛型方法
public class Test {
public static void main(String[] args) {
Integer[] arr ={1,2,3};
swap(arr,1,2);
}
//這里靜態(tài)泛型方法前面要說明是什么類型
public static <T> void swap(T[] array,int i,int j){
T tem = array[i];
array[i] = array[j];
array[j] = tem;
}
}
這里前面的T是不可以省略的,用于確定其是什么類型

1.類名后的 <T> 代表占位符,表?當(dāng)前類是?個泛型類 E表?Element, K表?Key , V表?Value ,N表?Number ,T表?Type 2.創(chuàng)建對象的時候就確認(rèn)其數(shù)組數(shù)據(jù)類型,并且只可以是包裝類型 3.確認(rèn)數(shù)據(jù)類型就不可以在其數(shù)組放入其他數(shù)據(jù)類型的數(shù)據(jù)了
泛型的上界
在定義泛型類的時候有時候我們要對其傳入數(shù)據(jù)類型進(jìn)行限制,于是就引出了泛型的上界
class 泛型類名稱<類型形參 extends 類型邊界> {
…
}
例如上面
public class MyArray< E extends Number> {
…
}
//這里表示上界是Number
例如
class MyArray<T extends Number>{
public Object[] array = new Object[10];
public T getval(int index){
return (T)array[index];
}
public void setval(int index,int val){
this.array[index] = val;
}
}
例如上面這個類就是上界是Number
也就是這里是要是int double float類型等等數(shù)字類型
public class Test {
public static void main(String[] args) {
MyArray<Integer> myArray = new MyArray<>();
MyArray<Double> myArray1 = new MyArray<>();
MyArray<Float> myArray2 = new MyArray<>();
}
}
這里要求的上界是Number數(shù)字,如果不是數(shù)字類型的包裝類型就會報錯,例如下面?zhèn)魅胍脭?shù)據(jù)類型就會報錯

通配符
通配符概念
?也可以用于泛型的使用,也就是通配符
class Message<T>{
private T message;
public T getMessage() {
return message;
}
public void setMessage(T message) {
this.message = message;
}
}
public class Test {
public static void main(String[] args) {
Message<String> message = new Message<>();
message.setMessage("hello world");
fun(message);
}
public static void fun(Message<String> message){
System.out.println(message.getMessage());
}
}
運行結(jié)果如下

我們發(fā)現(xiàn)上面的fun函數(shù)并不是泛型,只可以打印和接收String類型,如果是其他的類型就會報錯,這明顯不符合我們的需求,我們要其可以接收和打印多種類型
如果這里傳入Integer類型就會報錯

因此這時候我們就可以使用通配符?
public class Test {
public static void main(String[] args) {
Message<String> message = new Message<>();
message.setMessage("hello world");
fun(message);
Message<Integer> message1 = new Message<>();
message1.setMessage(1111);
fun(message1);
}
//傳入什么類型,這個就是什么類型
public static void fun(Message<?> message){
System.out.println(message.getMessage());
}
}
運行結(jié)果如下

其實這里我們使用上面的泛型也可以
public static<T> void fun(Message<T> message){
System.out.println(message.getMessage());
}
通配符上界
<?extend 上界>
定義了一個Food類

class Food{
}
class Fruit extends Food{
}
class Banana extends Fruit{
}
class Apple extends Fruit{
}
class Plate<T>{
private T plate;
public T getPlate() {
return plate;
}
public void setPlate(T plate) {
this.plate = plate;
}
}
public class Test {
public static void main(String[] args) {
//這里的類型要為Fruit或者其子類
Plate<Apple> plate1 = new Plate<>();
plate1.setPlate(new Apple());
fun(plate1);
Plate<Banana> plate2 = new Plate<>();
plate2.setPlate(new Banana());
fun(plate2);
// fun(new Food());//這個超越了上界
}
//fun用于打印
//這里表示只可以傳入Fruit及其子類
public static void fun(Plate<? extends Fruit> plate){
// plate.setPlate(new Apple());
// plate.setPlate(new Banana());
//在這里不可以添加元素,因為這里的plate不知道是那個的子類,報錯
System.out.println(plate.getPlate());
}
}
運行結(jié)果如下

這里的fun函數(shù)參數(shù)的上界為Fruit,所以其只可以接收,F(xiàn)ruit及其子類
如果傳入Food,是Fruit的父類肯定報錯,超越了上界

并且不可以在其fun函數(shù)里,來進(jìn)行添加元素
因為這里的plate是那個子類我們并不知道,不知道添加什么類型的元素

通配符下界
<? super 下界>
還是利用上面的
class Food{
}
class Fruit extends Food{
}
class Banana extends Fruit{
}
class Apple extends Fruit{
}
class Plate<T>{
private T plate;
public T getPlate() {
return plate;
}
public void setPlate(T plate) {
this.plate = plate;
}
}
public class Test {
public static void main(String[] args) {
Plate<Fruit> plate = new Plate<>();
plate.setPlate(new Fruit());
fun(plate);
Plate<Food> plate1 = new Plate<>();
plate1.setPlate(new Food());
fun(plate1);
// Plate<Apple> plate2 = new Plate<>();
// plate2.setPlate(new Apple());
// fun(plate2);//下界為Fruit,只可以傳入Fruit及其子類
}
public static void fun(Plate<? super Fruit> plate){
System.out.println(plate.getPlate());
}
}
運行結(jié)果如下

這里下界為Fruit,只可以傳入Fruit及其父類
不可以傳入其子類

由于這里fun函數(shù)接收的下界為Fruit,所以其是可以在里面添加其Fruit子類對象
public static void fun(Plate<? super Fruit> plate){
plate.setPlate(new Apple());
plate.setPlate(new Banana());
plate.setPlate(new Fruit());
System.out.println(plate.getPlate());
}
雖然可以添加,但是不可以接收,因為不知道是用哪一個父類來接收,F(xiàn)ruit可能有很多父類

到這里就結(jié)束了。
以上就是一文詳解Java中的包裝類和泛型的詳細(xì)內(nèi)容,更多關(guān)于Java包裝類和泛型的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
struts2中通過json傳值解決亂碼問題的實現(xiàn)方法
這篇文章主要介紹了struts2中通過json傳值解決亂碼問題的實現(xiàn)方法,涉及js編碼及java解碼的相關(guān)操作技巧,需要的朋友可以參考下2016-06-06
解決Eclipse add external jars運行出現(xiàn)java.lang.NoClassDefFoundErro
本篇文章對Eclipse add external jars導(dǎo)致運行出現(xiàn)java.lang.NoClassDefFoundError的解決方法進(jìn)行了詳細(xì)的分析介紹。需要的朋友參考下2013-05-05
詳解Spring中Bean后置處理器(BeanPostProcessor)的使用
BeanPostProcessor 接口也被稱為Bean后置處理器,通過該接口可以自定義調(diào)用初始化前后執(zhí)行的操作方法。本文將詳細(xì)講講它的使用,需要的可以參考一下2022-06-06
Java語言實現(xiàn)簡單FTP軟件 FTP軟件本地窗口實現(xiàn)(5)
這篇文章主要為大家詳細(xì)介紹了Java語言實現(xiàn)簡單FTP軟件,F(xiàn)TP軟件本地窗口的實現(xiàn)方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03

