Java泛型示例-泛型方法,類,接口

Java 泛型示例 - 泛型方法,類,接口

十載的歙縣網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。營銷型網(wǎng)站的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整歙縣建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。成都創(chuàng)新互聯(lián)從事“歙縣網(wǎng)站設(shè)計(jì)”,“歙縣網(wǎng)站推廣”以來,每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。

Java Genrics 是 Java 5 中引入的最重要的功能之一。

如果您一直在使用Java Collections并使用版本 5 或更高版本,那么我確定您已經(jīng)使用過它。

Java 中具有集合類的泛型非常容易,但是它提供了比僅創(chuàng)建集合類型更多的功能。

我們將在本文中嘗試學(xué)習(xí)泛型的功能。如果我們使用專業(yè)術(shù)語,對(duì)泛型的理解有時(shí)會(huì)變得混亂,因此,我將盡量保持其簡單易懂。

1. Java 中的泛型

Java 5 中添加了泛型,以提供編譯時(shí)類型檢查,并消除了ClassCastException使用集合類時(shí)常見的風(fēng)險(xiǎn)。整個(gè)收集框架都進(jìn)行了重寫,以使用泛型進(jìn)行類型安全。讓我們看看泛型如何幫助我們安全地使用集合類。

List list = new ArrayList();
list.add("abc");
list.add(new Integer(5)); 

for(Object obj : list){

    String str=(String) obj; 
}

上面的代碼可以很好地編譯,但是在運(yùn)行時(shí)會(huì)引發(fā)ClassCastException,因?yàn)槲覀冊噲D將列表中的對(duì)象強(qiáng)制轉(zhuǎn)換為String,而其中一個(gè)元素是Integer類型。在Java 5之后,我們使用如下收集類。

List<String> list1 = new ArrayList<String>(); // java 7 ? List<String> list1 = new ArrayList<>();
list1.add("abc");
//list1.add(new Integer(5)); //編譯錯(cuò)誤

for(String str : list1){
     //no type casting needed, avoids ClassCastException
}

請(qǐng)注意,在創(chuàng)建列表時(shí),我們已指定列表中元素的類型為String。因此,如果我們嘗試在列表中添加任何其他類型的對(duì)象,則該程序?qū)⒁l(fā)編譯時(shí)錯(cuò)誤。還要注意,在循環(huán)中中,我們不需要列表中元素的類型轉(zhuǎn)換,因此在運(yùn)行時(shí)刪除了ClassCastException。

2. Java通用類

我們可以使用泛型類型定義自己的類。泛型類型是通過類型進(jìn)行參數(shù)化的類或接口。我們使用尖括號(hào)(<>)來指定類型參數(shù)。

為了了解其好處,我們假設(shè)有一個(gè)簡單的類:

package com.journaldev.generics;
public class GenericsTypeOld {
    private Object t;
    public Object get() {
        return t;
    }
    public void set(Object t) {
        this.t = t;
    }
        public static void main(String args[]){
        GenericsTypeOld type = new GenericsTypeOld();
        type.set("Pankaj");
         String str = (String) type.get(); //type casting, error prone and can cause ClassCastException
    }
}

請(qǐng)注意,在使用此類時(shí),我們必須使用類型轉(zhuǎn)換,并且它可以在運(yùn)行時(shí)產(chǎn)生ClassCastException?,F(xiàn)在,我們將使用Java通用類替換如下所示的相同類。

package com.journaldev.generics;
public class GenericsType<T> {
    private T t;
    public T get(){
        return this.t;
    }
    public void set(T t1){
        this.t=t1;
    }
    public static void main(String args[]){
        GenericsType<String> type = new GenericsType<>();
        type.set("Pankaj"); //valid
        GenericsType type1 = new GenericsType(); //raw type
        type1.set("Pankaj"); //valid
        type1.set(10); //valid and autoboxing support
    }
}

注意main方法中GenericsType類的使用。我們不需要進(jìn)行類型轉(zhuǎn)換,并且可以在運(yùn)行時(shí)刪除ClassCastException。如果我們在創(chuàng)建時(shí)未提供類型,則編譯器將發(fā)出警告,“ GenericsType是原始類型。

泛型類型GenericsType 的引用應(yīng)參數(shù)化”。當(dāng)我們不提供類型時(shí),該類型就變成了類型Object,因此它允許String和Integer對(duì)象。但是,我們應(yīng)始終嘗試避免這種情況,因?yàn)樵谔幚砜赡墚a(chǎn)生運(yùn)行時(shí)錯(cuò)誤的原始類型時(shí),我們必須使用類型轉(zhuǎn)換。

還要注意,它支持Java自動(dòng)裝箱。

3. Java通用接口

Comparable接口是接口中泛型的一個(gè)很好的例子,它寫為:

package java.lang;
import java.util.*;

public interface Comparable<T> {
    public int compareTo(T o);
}

以類似的方式,我們可以在Java中創(chuàng)建通用接口。我們也可以像Map界面具有多個(gè)類型參數(shù)。同樣,我們也可以為參數(shù)化類型提供參數(shù)化值,例如new HashMap<String, List<String>>();有效。

4. Java通用類型

Java通用類型命名約定可以幫助我們輕松理解代碼,并且具有命名約定是Java編程語言的最佳實(shí)踐之一。因此,泛型也帶有自己的命名約定。通常,類型參數(shù)名稱是單個(gè)大寫字母,以可以實(shí)現(xiàn)與Java變量區(qū)分開。最常用的類型參數(shù)名稱為:

  • E –元素由Java Collections Framework廣泛使用,例如ArrayList,Set等
  • K –鍵(在Map中使用)
  • N –數(shù)字
  • T –類型
  • V –值(在Map中使用)
  • S,U,V等–第二,第三,第四類型

5. Java通用方法

有時(shí)我們不希望整個(gè)類都被參數(shù)化,在這種情況下,我們可以創(chuàng)建java泛型方法。由于構(gòu)造函數(shù)是一種特殊的方法,因此我們也可以在構(gòu)造函數(shù)中使用泛型類型。

這是一個(gè)顯示Java泛型方法示例的類。

package com.journaldev.generics;
public class GenericsMethods {
    //Java Generic Method
    public static <T> boolean isEqual(GenericsType<T> g1, GenericsType<T> g2){
        return g1.get().equals(g2.get());
    }
    public static void main(String args[]){
        GenericsType<String> g1 = newGenericsType<>();
        g1.set("Pankaj");
        GenericsType<String> g2 = new GenericsType<>();
        g2.set("Pankaj");
        boolean isEqual = GenericsMethods.<String>isEqual(g1, g2);
        //above statement can be written simply as
        isEqual = GenericsMethods.isEqual(g1, g2);
        //This feature, known as type inference, allows you to invoke a generic method as an ordinary method, without specifying a type between angle brackets.
        //Compiler will infer the type that is needed
    }
}

注意的isEqual方法簽名顯示了在方法中使用泛型類型的語法。另外,請(qǐng)注意如何在我們的Java的程序中使用這些方法。我們可以在調(diào)用這些方法時(shí)指定類型,也可以像普通方法一樣調(diào)用它們。Java編譯器足夠聰明,可以確定要使用的變量的類型,這種功能稱為類型變量。

6. Java泛型綁定類型參數(shù)

假設(shè)我們要限制可以在參數(shù)化類型中使用的對(duì)象的類型,例如在比較兩個(gè)對(duì)象的方法中,并且我們要確保接受的對(duì)象是可比較的。要聲明一個(gè)有界的類型參數(shù),請(qǐng)列出類型參數(shù)的名稱,然后列出擴(kuò)展關(guān)鍵字,再加上其上限,以下下面的方法。

public static <T extends Comparable<T>> int compare(T t1, T t2){
        return t1.compareTo(t2);
}

這些方法的調(diào)用與***方法類似,不同之處在于,如果我們嘗試使用任何非Comparable的類,則引發(fā)編譯時(shí)錯(cuò)誤。

綁定類型參數(shù)可以與方法以及類和接口一起使用。

Java泛型也支持多個(gè)范圍,即。在這種情況下,A可以是接口或類。如果A是類,則B和C應(yīng)該是接口。在多個(gè)范圍內(nèi),我們不能有多個(gè)類。

7. Java泛型和繼承

我們知道,如果A是B的子類,則Java繼承允許我們將變量A分配給另一個(gè)變量B。因此,我們可能認(rèn)為可以將A的任何泛型類型分配給B的泛型類型,但事實(shí)并非如此。讓我們用一個(gè)簡單的程序看看。

package com.journaldev.generics;
public class GenericsInheritance {
    public static void main(String[] args) {
        String str = "abc";
        Object obj = new Object();
        obj=str; // works because String is-a Object, inheritance in java
        MyClass<String> myClass1 = new MyClass<String>();
        MyClass<Object> myClass2 = new MyClass<Object>();
        //myClass2=myClass1; // compilation error since MyClass<String> is not a MyClass<Object>
        obj = myClass1; // MyClass<T> parent is Object
    }
    public static class MyClass<T>{}
}

我們永久將MyClass 變量分配給MyClass 變量,因?yàn)樗鼈儾幌嚓P(guān),實(shí)際上MyClass 的父對(duì)象是Object。

8. Java通用類和子類型

我們可以通過擴(kuò)展或?qū)崿F(xiàn)來泛型一個(gè)通用類或接口。一個(gè)類或接口的類型參數(shù)與另一類或接口的類型參數(shù)之間的關(guān)系由extend和實(shí)現(xiàn)子句確定。

例如,ArrayList 實(shí)現(xiàn)了擴(kuò)展Collection 的List ,因此ArrayList 是List 的子類型,而List 是Collection 的子類型。

只要不更改type參數(shù),子類型關(guān)系就會(huì)保留,下面顯示了多個(gè)type參數(shù)的示例。

interface MyList<E,T> extends List<E>{
}

List 的子類型可以是MyList ,MyList 等。

9. Java通用通配符

問號(hào)(?)是泛型中的通配符,表示未知類型。通配符可以用作參數(shù),字段或局部變量的類型,有時(shí)還可以用作返回類型。在調(diào)用通用方法或?qū)嵗ㄓ妙悤r(shí),不能使用通配符。在以下各節(jié)中,我們將學(xué)習(xí)上界通配符,下界通配符和通配符捕獲。

9.1)Java泛型上界通配符

上限通配符用于在方法中放寬對(duì)變量類型的限制。假設(shè)我們要編寫一個(gè)將返回列表中數(shù)字總和的方法,那么我們的實(shí)現(xiàn)將是這樣的。

現(xiàn)在,上述實(shí)現(xiàn)的問題在于它不適用于Integers或Doubles,因?yàn)槲覀冎繪ist 和List 不相關(guān),這在使用高層通配符時(shí)很有用。我們將通用通配符與extends關(guān)鍵字和上級(jí)類或接口一起使用,這將允許我們傳遞上級(jí)子類類型的參數(shù)。

public static double sum(List<Number> list){
    double sum = 0;
    for(Number n : list){
        sum += n.doubleValue();
    }
    return sum;
}

可以像下面的程序一樣修改上面的實(shí)現(xiàn)。

package com.journaldev.generics;
import java.util.ArrayList;
import java.util.List;
public class GenericsWildcards {
    public static void main(String[] args) {
        List<Integer> ints = new ArrayList<>();
        ints.add(3); ints.add(5); ints.add(10);
        double sum = sum(ints);
        System.out.println("Sum of ints="+sum);
    }
    public static double sum(List<? extends Number> list){
        double sum = 0;
        for(Number n : list){
            sum += n.doubleValue();
        }
        return sum;
    }
}

就像按照接口編寫代碼一樣,在上述方法中,我們可以使用上限類號(hào)碼的所有方法。請(qǐng)注意,對(duì)于上界列表,除空之外,我們不允許將任何對(duì)象添加到列表中。如果我們嘗試在sum方法內(nèi)將元素添加到列表中,則該程序?qū)o法編譯。

9.2)Java泛型無限制通配符

有時(shí),我們希望通用方法適用于所有類型,在這種情況下,可以使用***通配符。與使用<?extends Object>。

public static void printData(List<?> list){
    for(Object obj : list){
        System.out.print(obj + "::");
    }
}

我們可以為PrintData方法提供List 或List 或任何其他類型的Object列表參數(shù)。與上限列表類似,我們可以在列表中添加任何內(nèi)容。

9.3)Java泛型下界通配符

假設(shè)我們要在方法中將整體添加到整數(shù)列表中,我們可以將參數(shù)類型保持為List,但可以與Integers捆綁在一起,而List 和List 也可以容納整數(shù),因此我們可以使用下限通配符來實(shí)現(xiàn)。我們使用超級(jí)關(guān)鍵字和下限類的泛型通配符(?)來實(shí)現(xiàn)此目的。

我們可以傳遞下界或下界的任何超類型作為參數(shù),在這種情況下,java編譯器允許將下界對(duì)象類型添加到列表中。

public static void addIntegers(List<? super Integer> list){
    list.add(new Intege(50));
}

10.使用泛型通配符進(jìn)行子類型化

List<? extends Integer> intList = new ArrayList<>();
List<? extends Number>  numList = intList;  // OK. List<? extends Integer> is a subtype of List<? extends Number>

11. Java泛型類型重構(gòu)

添加了Java泛型以在編譯時(shí)提供類型檢查,并且在運(yùn)行時(shí)沒有使用,因此Java編譯器使用類型更改功能刪除字節(jié)碼中的所有泛型類型檢查代碼,并在必要時(shí)插入類型轉(zhuǎn)換。類型定義可確保不會(huì)為參數(shù)化類型創(chuàng)建新的類;因此,泛型不會(huì)產(chǎn)生運(yùn)行時(shí)浪費(fèi)。

例如,如果我們有如下通用類;

public class Test<T extends Comparable<T>> {
    private T data;
    private Test<T> next;
    public Test(T d, Test<T> n) {
        this.data = d;
        this.next = n;
    }
    public T getData() { return this.data; }
}

Java編譯器用第一個(gè)綁定接口Comparable替換有界類型參數(shù)T,如下代碼:

public class Test {
    private Comparable data;
    private Test next;
    public Node(Comparable d, Test n) {
        this.data = d;
        this.next = n;
    }
    public Comparable getData() { return data; }
}

12.泛型常見問題解答

12.1)為什么我們在Java中使用泛型?

泛型提供了強(qiáng)大的編譯時(shí)類型檢查,并降低了ClassCastException和顯式對(duì)象轉(zhuǎn)換的風(fēng)險(xiǎn)。

12.2)泛型中的T是什么?

我們使用創(chuàng)建通用類,接口和方法。我們在使用T時(shí)將其替換為實(shí)際類型。

12.3)泛型如何在Java中工作?

通用代碼可確保類型安全。編譯器使用類型預(yù)先在編譯時(shí)刪除所有類型參數(shù),以減少運(yùn)行時(shí)的重載。

13. Java泛型–進(jìn)一步閱讀

  • 泛型不支持子類型,因此List numbers = new ArrayList();將不進(jìn)行編譯
  • 我們無法創(chuàng)建通用副本,因此List[] array = new ArrayList[10]無法編譯

這是所有的Java泛型,Java泛型是非常龐大的,需要大量的時(shí)間來了解和有效地使用它。本文提供了泛型的基本細(xì)節(jié),以及如何使用泛型來擴(kuò)展程序的類型安全性。

網(wǎng)頁名稱:Java泛型示例-泛型方法,類,接口
網(wǎng)頁URL:http://bm7419.com/article14/igsdge.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供軟件開發(fā)、App開發(fā)關(guān)鍵詞優(yōu)化、網(wǎng)站收錄、外貿(mào)建站網(wǎng)站導(dǎo)航

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

小程序開發(fā)