欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java知識(shí)梳理之泛型用法詳解

 更新時(shí)間:2022年08月08日 11:35:41   作者:沈七_(dá)  
從JDK?5.0以后,Java引入了“參數(shù)化類型(Parameterized?type)”的概念,允許我們?cè)趧?chuàng)建集合時(shí)再指定集合元素的類型。本文就來和大家深入聊聊Java泛型的使用

泛型

背景:

從JDK 5.0以后,Java引入了“參數(shù)化類型(Parameterized type)”的概念,允許我們?cè)趧?chuàng)建集合時(shí)再指定集合元素的類型,正如:List ,這表明該List只能保存字符串類型的對(duì)象。

作用

解決元素存儲(chǔ)的安全性問題,好比商品、藥品標(biāo)簽,不會(huì)弄錯(cuò)。

解決獲取數(shù)據(jù)元素時(shí),需要類型強(qiáng)制轉(zhuǎn)換的問題,好比不用每回拿商品、藥品都要辨別。

@Test
public void test1(){
    ArrayList list = new ArrayList();
    //需求:存放學(xué)生的成績
    list.add(78);
    list.add(76);
    list.add(89);
    list.add(88);
    //問題一:類型不安全
    //        list.add("Tom");

    for(Object score : list){
        //問題二:強(qiáng)轉(zhuǎn)時(shí),可能出現(xiàn)ClassCastException
        int stuScore = (Integer) score;
    
        System.out.println(stuScore);
    }
}

//在集合中使用泛型,以ArrayList為例
@Test
public void test1(){
    ArrayList<String> list = new ArrayList<>();
    list.add("AAA");
    list.add("BBB");
    list.add("FFF");
    list.add("EEE");
    list.add("CCC");
    //遍歷方式一:
    Iterator<String> iterator = list.iterator();
    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }
    System.out.println("-------------");
    //便利方式二:
    for (String str:
         list) {
        System.out.println(str);
    }
}

集合中泛型

① 集合接口或集合類在JDK 5.0時(shí)都修改為帶泛型的結(jié)構(gòu)。

② 在實(shí)例化集合類時(shí),可以指明具體的泛型類型

③ 指明完以后,在集合類或接口中凡是定義類或接口時(shí),內(nèi)部結(jié)構(gòu)(比如:方法、構(gòu)造器、屬性等)使用到類的泛型的位置,都指定為實(shí)例化的泛型類型。

比如:add(E e) —>實(shí)例化以后:add(Integer e)

④ 注意點(diǎn):泛型的類型必須是類,不能是基本數(shù)據(jù)類型。需要用到基本數(shù)據(jù)類型的位置,拿包裝類替換

⑤ 如果實(shí)例化時(shí),沒有指明泛型的類型。默認(rèn)類型為 java.lang.Object 類型

說明

1.泛型類可能有多個(gè)參數(shù),此時(shí)應(yīng)將多個(gè)參數(shù)一起放在尖括號(hào)內(nèi)。比如<E1,E2,E3>

2.泛型類的構(gòu)造器如下: public GenericClass(){}

而下面是錯(cuò)誤的: public GenericClass<E>{}

3.實(shí)例化后,操作原來泛型位置的結(jié)構(gòu)必須與指定的泛型類型一致。

4.泛型不同的引用不能相互賦值。

盡管在編譯時(shí) ArrayList和ArrayList是兩種類型,但是,在運(yùn)行時(shí)只有一個(gè)ArrayList被加載到JVM中。

5.泛型如果不指定,將被擦除,泛型對(duì)應(yīng)的類型均按照Object處理,但不等價(jià)于Object。

建議:泛型要使用一路都用。要不用,一路都不要用。

6.如果泛型結(jié)構(gòu)是一個(gè)接口或抽象類,則不可創(chuàng)建泛型類的對(duì)象。

7.JDK 7.0,泛型的簡化操作: ArrayList<Fruit>first= new ArrayList<>();(類型推斷)

8.泛型的指定中不能使用基本數(shù)據(jù)類型,可以使用包裝類替換。

9.在類/接口上聲明的泛型,在本類或本接口中即代表某種類型,可以作為非靜態(tài)屬性的類型、非靜態(tài)方法的參數(shù)類型、非靜態(tài)方法的返回值類型。但在靜態(tài)方法中不能使用類的泛型。

10.異常類不能是泛型的。

11.不能使用 new E[]。但是可以:E[] elements= (E[])new Object[capacity];

參考:ArrayList源碼中聲明:Object[] elementData,而非泛型參數(shù)類型數(shù)組。

12.父類有泛型,子類可以選擇保留泛型也可以選擇指定泛型類型

子類不保留父類的泛型:按需實(shí)現(xiàn)

  • 沒有類型—擦除
  • 具體類型

子類保留父類的泛型:泛型子類

  • 全部保留
  • 部分保留

結(jié)論:子類必須是“富二代”,子類除了指定或保留父類的泛型,還可以增加自己的泛型

自定義泛型

泛型類、泛型接口、泛型方法

泛型的聲明

interface List<T> 和 class GenTest<K,V> 其中,T,K,V,不代表值,而是表示類型。這里使用任意字母都可以。

常用T表示,是Type的縮寫。

泛型的實(shí)例化

一定要在類名后面指定類型參數(shù)的值(類型)。如:

List<String> strList =new ArrayList<String>();
Iterator<Customer> iterator = customers.iterator();

T只能是類,不能用基本數(shù)據(jù)類型填充。但可以使用包裝類填充

把一個(gè)集合中的內(nèi)容限制為一個(gè)特定的數(shù)據(jù)類型,這就是 generics背后的核心思想

//JDK 5.0以前
Comparable c = new Date();
System.out.println(c.comparaTo("red");
                   
//JDK 5.0以后
Comparable <Date> c = new Date();
System.out.println(c.comparaTo("red");                   

自定義泛型類

代碼示例:

/**
 * 自定義泛型類Order
 */
class Order<T> {
    private String orderName;
    private int orderId;
    //使用T類型定義變量
    private T orderT;

    public Order() {
    }
    //使用T類型定義構(gòu)造器
    public Order(String orderName, int orderId, T orderT) {
        this.orderName = orderName;
        this.orderId = orderId;
        this.orderT = orderT;
    }

    //這個(gè)不是泛型方法
    public T getOrderT() {
        return orderT;
    }
    //這個(gè)不是泛型方法
    public void setOrderT(T orderT) {
        this.orderT = orderT;
    }
    //這個(gè)不是泛型方法
    @Override
    public String toString() {
        return "Order{" +
                "orderName='" + orderName + '\'' +
                ", orderId=" + orderId +
                ", orderT=" + orderT +
                '}';
    }
//    //靜態(tài)方法中不能使用類的泛型。
//    public static void show(T orderT){
//        System.out.println(orderT);
//    }

//    //try-catch中不能是泛型的。
//    public void show(){
//        try {
//
//        }catch (T t){
//
//        }
//    }

    //泛型方法:在方法中出現(xiàn)了泛型的結(jié)構(gòu),泛型參數(shù)與類的泛型參數(shù)沒有任何關(guān)系。
    //換句話說,泛型方法所屬的類是不是泛型類都沒有關(guān)系。
    //泛型方法,可以聲明為靜態(tài)的。
    // 原因:泛型參數(shù)是在調(diào)用方法時(shí)確定的。并非在實(shí)例化類時(shí)確定。
    public static <E> List<E> copyFromArryToList(E[] arr) {
        ArrayList<E> list = new ArrayList<>();
        for (E e :
                list) {
            list.add(e);
        }
        return list;
    }
}

自定義泛型接口

代碼示例:

/**
 * 自定義泛型接口
 */
public interface DemoInterface <T> {
    void show();
    int size();
}

//實(shí)現(xiàn)泛型接口
public class Demo implements DemoInterface {
    @Override
    public void show() {
        System.out.println("hello");
    }

    @Override
    public int size() {
        return 0;
    }
}

@Test
//測(cè)試泛型接口
public void test3(){
    Demo demo = new Demo();
    demo.show();
}

自定義泛型方法

方法,也可以被泛型化,不管此時(shí)定義在其中的類是不是泛型類。在泛型方法中可以定義泛型參數(shù),此時(shí),參數(shù)的類型就是傳入數(shù)據(jù)的類型。

泛型方法的格式: [訪問權(quán)限]<泛型>返回類型 方法名(泛型標(biāo)識(shí) 參數(shù)名稱])拋出的異常

泛型方法聲明泛型時(shí)也可以指定上限

泛型方法聲明泛型時(shí)也可以指定上限

代碼示例:

//泛型方法:在方法中出現(xiàn)了泛型的結(jié)構(gòu),泛型參數(shù)與類的泛型參數(shù)沒有任何關(guān)系。
//換句話說,泛型方法所屬的類是不是泛型類都沒有關(guān)系。
//泛型方法,可以聲明為靜態(tài)的。
// 原因:泛型參數(shù)是在調(diào)用方法時(shí)確定的。并非在實(shí)例化類時(shí)確定。
public static <E> List<E> copyFromArryToList(E[] arr) {
    ArrayList<E> list = new ArrayList<>();
    for (E e :
         list) {
        list.add(e);
    }
    return list;
}

通配符

1.通配符的使用

使用類型通配符:?

比如:List<?>,Map<?,?>

List<?> 是 List<String>、List<Object> 等各種泛型 List 的父類。

讀取 List<?> 的對(duì)象list中的元素時(shí),永遠(yuǎn)是安全的,因?yàn)椴还躭ist的真實(shí)類型是什么,它包含的都是Object

寫入list中的元素時(shí),不可以。因?yàn)槲覀儾恢纁的元素類型,我們不能向其中添加對(duì)象。 除了添加null之外。

說明:

將任意元素加入到其中不是類型安全的

Collection<?> c = new ArrayList<String>()

c.add(new Object());//編譯時(shí)錯(cuò)誤

因?yàn)槲覀儾恢纁的元素類型,我們不能向其中添加對(duì)象。add 方法有類型參數(shù) E 作為集合的元素類型。我們傳給add的任何參數(shù)都必須是一個(gè)已知類型的子類。因?yàn)槲覀儾恢滥鞘鞘裁搭愋?,所以我們無法傳任何東西進(jìn)去。

唯一的例外的是 null,它是所有類型的成員。

我們可以調(diào)用 get() 方法并使用其返回值。返回值是一個(gè)未知的類型,但是我們知道,它總是一個(gè)Object。

代碼示例:

@Test
public void test3(){
    List<Object> list1 = null;
    List<String> list2 = null;

    List<?> list = null;

    list = list1;
    list = list2;
    //編譯通過
    //        print(list1);
    //        print(list2);

    //
    List<String> list3 = new ArrayList<>();
    list3.add("AA");
    list3.add("BB");
    list3.add("CC");
    list = list3;
    //添加(寫入):對(duì)于List<?>就不能向其內(nèi)部添加數(shù)據(jù)。
    //除了添加null之外。
    //        list.add("DD");
    //        list.add('?');

    list.add(null);

    //獲取(讀取):允許讀取數(shù)據(jù),讀取的數(shù)據(jù)類型為Object。
    Object o = list.get(0);
    System.out.println(o);
}

public void print(List<?> list){
    Iterator<?> iterator = list.iterator();
    while(iterator.hasNext()){
        Object obj = iterator.next();
        System.out.println(obj);
    }
}

2.注意點(diǎn)

//注意點(diǎn)1:編譯錯(cuò)誤:不能用在泛型方法聲明上,返回值類型前面<>不能使用?
public static <?> void test(ArrayList<?> list){
    
}

//注意點(diǎn)2:編譯錯(cuò)誤:不能用在泛型類的聲明上
class GenericTypeClass<?>{
    
}

//注意點(diǎn)3:編譯錯(cuò)誤:不能用在創(chuàng)建對(duì)象上,右邊屬于創(chuàng)建集合對(duì)象
ArrayList<> list2 new ArrayList<?>();

3.有限制的通配符

1.<?>:允許所有泛型的引用調(diào)用

2.通配符指定上限

上限 extends:使用時(shí)指定的類型必須是繼承某個(gè)類,或者實(shí)現(xiàn)某個(gè)接口,即 <=

3.通配符指定下限

下限 super:使用時(shí)指定的類型不能小于操作的類,即 >=

4.舉例:

<?extends Number>(無窮小, Number\]

只允許泛型為Number及Number子類的引用調(diào)用

<?super Number>\[Number,無窮大)

只允許泛型為Number及Number父類的引用調(diào)用

<? extends Comparable>

只允許泛型為實(shí)現(xiàn) Comparable接口的實(shí)現(xiàn)類的引用調(diào)用

代碼示例:

@Test
public void test4(){

    List<? extends Person> list1 = null;
    List<? super Person> list2 = null;

    List<Student> list3 = new ArrayList<Student>();
    List<Person> list4 = new ArrayList<Person>();
    List<Object> list5 = new ArrayList<Object>();

    list1 = list3;
    list1 = list4;
    //        list1 = list5;

    //        list2 = list3;
    list2 = list4;
    list2 = list5;

    //讀取數(shù)據(jù):
    list1 = list3;
    Person p = list1.get(0);
    //編譯不通過
    //Student s = list1.get(0);

    list2 = list4;
    Object obj = list2.get(0);
    編譯不通過
    //        Person obj = list2.get(0);

    //寫入數(shù)據(jù):
    //編譯不通過
    //        list1.add(new Student());

    //編譯通過
    list2.add(new Person());
    list2.add(new Student());

}

到此這篇關(guān)于Java知識(shí)梳理之泛型用法詳解的文章就介紹到這了,更多相關(guān)Java泛型內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • break和continue的作用和區(qū)別解析(案例分析)

    break和continue的作用和區(qū)別解析(案例分析)

    break和continue都是用來控制循環(huán)結(jié)構(gòu)的,主要作用是停止循環(huán),這篇文章主要介紹了break和continue的作用和區(qū)別,需要的朋友可以參考下
    2023-03-03
  • Java 輸入流中的read(byte[] b)方法詳解

    Java 輸入流中的read(byte[] b)方法詳解

    這篇文章主要介紹了Java 輸入流中的read(byte[] b)方法詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • Mybatis使用useGeneratedKeys獲取自增主鍵的方法

    Mybatis使用useGeneratedKeys獲取自增主鍵的方法

    這篇文章主要給大家介紹了關(guān)于Mybatis使用useGeneratedKeys獲取自增主鍵的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Mybatis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Spring Boot框架中的@Conditional注解示例詳解

    Spring Boot框架中的@Conditional注解示例詳解

    這篇文章主要介紹了Spring Boot框架中的@Conditional系列注解,@ConditionalOnProperty注解的作用是解析application.yml/application.properties 里的配置生成條件來生效,也是與@Configuration注解一起使用,本文通過示例代碼給大家介紹的非常詳細(xì),需要的朋友一起看看吧
    2022-09-09
  • Spring Boot如何使用Spring Security進(jìn)行安全控制

    Spring Boot如何使用Spring Security進(jìn)行安全控制

    要實(shí)現(xiàn)訪問控制的方法多種多樣,可以通過Aop、攔截器實(shí)現(xiàn),也可以通過框架實(shí)現(xiàn),本文將具體介紹在Spring Boot中如何使用Spring Security進(jìn)行安全控制。
    2017-04-04
  • springboot集成mybatis-plus遇到的問題及解決方法

    springboot集成mybatis-plus遇到的問題及解決方法

    這篇文章主要介紹了springboot集成mybatis-plus遇到的問題及解決方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • Java設(shè)計(jì)模式筆記之Builder模式

    Java設(shè)計(jì)模式筆記之Builder模式

    建造者模式是日常開發(fā)中比較常見的設(shè)計(jì)模式,它的主要作用就是將復(fù)雜事物創(chuàng)建的過程抽象出來,該抽象的不同實(shí)現(xiàn)方式不同,創(chuàng)建出的對(duì)象也不同,這篇文章主要給大家介紹了關(guān)于Java設(shè)計(jì)模式筆記之Builder模式的相關(guān)資料,需要的朋友可以參考下
    2022-03-03
  • Java語言實(shí)現(xiàn)二叉堆的打印代碼分享

    Java語言實(shí)現(xiàn)二叉堆的打印代碼分享

    這篇文章主要介紹了Java語言實(shí)現(xiàn)二叉堆的打印代碼分享,具有一定借鑒價(jià)值,需要的朋友可以了解下。
    2017-12-12
  • Java中Arrays數(shù)組工具類的基本使用詳解

    Java中Arrays數(shù)組工具類的基本使用詳解

    Arrays類中的方法都是static修飾的靜態(tài)方法,在使用的時(shí)候可以直接使用類名進(jìn)行調(diào)用,而"不用"使用對(duì)象來調(diào)用(注意:是"不用"?而不是?"不能"),這篇文章主要給大家介紹了關(guān)于Java中Arrays數(shù)組工具類的基本使用,需要的朋友可以參考下
    2021-12-12
  • Spring在代碼中獲取bean的方法小結(jié)

    Spring在代碼中獲取bean的方法小結(jié)

    在工作中有時(shí)候我們需要在非spring依賴注入或管理的類中獲取service、dao等bean對(duì)象,這時(shí)候用@Autowired和@Resource顯然是不行的,那么下面這篇文章就給大家了整理幾種獲取bean的方式,對(duì)大家的學(xué)習(xí)和工作具有一定的參考借鑒,下面來一起看看吧。
    2016-11-11

最新評(píng)論