日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

我今天聊聊JAVA中的泛型, 它是一個廣泛使用但討論較少的主題。我們經常會使用它,但大多數開發人員并沒有真正了解它。

Java開發中你們肯定都用過List或者ArrayList。那你們應該記得如何定義他們吧?

List<Integer> list = new ArrayList<>(); // 這里的Integer 就是使用了泛型

這就是我們聲明的方式。所以,我們使用了泛型。這里,<Integer>是我們傳遞的指定類型。那是一個類型。在我們創建這樣的列表后,您只能將整數添加到列表中。

那如果我們不指定類型呢?

List numList = new ArrayList<>(); //不指定類型

如果我們像上面這樣定義列表,我們就可以將從 Object 超類擴展的任何類型的數據添加到列表中。

所以添加泛型后,我們可以實現此列表的類型安全

泛型意味著參數化類型。Java 讓我們創建一個類、接口和方法,可以在泛型域中與不同類型的數據(對象)一起使用。

泛型的優點是:

  • 代碼可重用性——我們可以使用具有多種對象類型的通用代碼
  • 編譯時類型檢查——Java 將在編譯時檢查泛型代碼是否有錯誤
  • 類型安全——我們可以限制添加不必要的數據
  • 集合中的用法——集合需要對象類型來處理數據

讓我們舉個例子來解釋為什么我們需要泛型。

想象一下,您必須使用打印機類打印數字和文本。打印機有一種在創建數據時接受數據的方法。

在傳統方式中,我們必須創建 2 個類,因為我們有 2 種數據類型:數字(整數)和文本(字符串)

public class TextPrinter {
    private final String data;

    public TextPrinter(String data) {
        this.data = data;
    }

    public void print() {
        System.out.println("print::: " + data);
    }
}
public class NumberPrinter {
    private final Integer data;

    public NumberPrinter(Integer data) {
        this.data = data;
    }

    public void print() {
        System.out.println("print::: " + data);
    }
}

使用:

public class GenericsMAIn {
    public static void main(String[] args) {
        NumberPrinter numberPrinter = new NumberPrinter(5);
        numberPrinter.print(); // 輸出 print::: 5
        TextPrinter textPrinter = new TextPrinter("Hello");
        textPrinter.print();   // 輸出  print::: Hello
    }
}

有沒有覺得代碼重復了?唯一的區別就是數據類型不同!

下面我們利用泛型來改造一下,使它成為一個通用的類型

public class Printer<T> {
    private final T data;

    public Printer(T data) {
        this.data = data;
    }

    public void print() {
        System.out.println("print::: " + data);
    }
}

使用:

Printer<Integer> integerPrinter = new Printer<>(5);
integerPrinter.print();   // 輸出 print::: 5

Printer<String> stringPrinter = new Printer<>("Hello");
stringPrinter.print();   // 輸出 print::: Hello

Printer<Double> doublePrinter = new Printer<>(45.34);
doublePrinter.print();   // 輸出 print::: 45.34

Printer<Long> longPrinter = new Printer<>(5L);
longPrinter.print();z    //輸出 print::: 5

現在我們就只寫了一個類,T用來表示作為通用標準的類型。我們甚至可以為其他數據類型(例如 Double/Long)創建打印對象。代碼可重用性是通過風格實現的。

我們還可以創建多個類型的通用類。如下:

public class MultiPrinter<T, V> {
    private final T data1;
    private final V data2;

    public MultiPrinter(T data1, V data2) {
        this.data1 = data1;
        this.data2 = data2;
    }

    public void print() {
        System.out.println("print::: " + data1 + " : " + data2);
    }
}
MultiPrinter<Integer, String> multiPrinter = new MultiPrinter<>(5, "Hello");
multiPrinter.print(); // 輸出 print::: 5 : Hello

Java 類型命名約定

  • E - 元素(用于集合)
  • K — 鍵(在地圖中使用)
  • N——數字
  • T——類型
  • V - 值(在地圖中使用)
  • S、U、V 等 — 第二、第三、第四類型

有界泛型

這是泛型的高級版本。我們可以通過有界泛型來限制更多并實現更多類型安全。

假設我們有一個AnimalPrinter類,它只能打印動物詳細信息。不允許與其他物體一起使用。如何實現這一目標?

public class Animal {
    private final String name;
    private final String color;
    private final Integer age;

    public Animal(String name, String color, Integer age) {
        this.name = name;
        this.color = color;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public String getColor() {
        return color;
    }

    public Integer getAge() {
        return age;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Animal animal = (Animal) o;
        return Objects.equals(name, animal.name) && Objects.equals(color, animal.color) && Objects.equals(age, animal.age);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, color, age);
    }
}

public class Cat extends Animal {
    public Cat(String name, String color, Integer age) {
        super(name, color, age);
    }
}

public class Dog extends Animal {
    public Dog(String name, String color, Integer age) {
        super(name, color, age);
    }
}
public class AnimalPrinter<T extends Animal> {
    private final T animalData;

    public AnimalPrinter(T animalData) {
        this.animalData = animalData;
    }

    public void print() {
        System.out.println("Name::: " + animalData.getName());
        System.out.println("Color::: " + animalData.getColor());
        System.out.println("Age::: " + animalData.getAge());
    }
}

在這個類中,T 擴展 Animal 部分完成了工作!我們限制了狗和貓的通用性!

AnimalPrinter<Cat> animalPrinter1 = new AnimalPrinter<>(new Cat("Jim", "brown", 2));
animalPrinter1.print();
AnimalPrinter<Dog> animalPrinter2 = new AnimalPrinter<>(new Dog("Rocky", "black", 5));
animalPrinter2.print();

多重界限

假設我們想向打印機通用功能添加更多功能。我們可以這樣實現。

public class AnimalPrinter<T extends Animal & Serializable> {
    ..................
}

我使用 Serialized 接口提供了 Serialized 功能。這里有一些重要的事情需要記住。

  • 我們必須在子類(Cat 和 Dog)中實現接口。
  • 類應該放在第一位,然后是 & 和接口。
  • 由于 Java 不支持多重繼承,因此只能擴展 1 個類。

泛型通配符

通配符由問號?表示 在 Java 中,我們用它們來指代未知類型。這可以用作泛型的參數類型。然后它將接受任何類型。在下面的代碼中,我使用通配符將任何對象的列表用作方法參數。

public static void printList(List<?> list) {
    System.out.println(list);
}

printList(
    Arrays.asList(
        new Cat("Jim", "brown", 2),
        new Dog("Rocky", "black", 5)
    )
);
printList(Arrays.asList(50, 60));
printList(Arrays.asList(50.45, 60.78));

// output:
// [generics.Cat@b1fa3959, generics.Dog@62294cd9]
// [50, 60]
// [50.45, 60.78]

列表現在可以是任何類型!

1??上限通配符

考慮這個例子:

public static void printAnimals(List<Animal> animals) {
      animals.forEach(Animal::eat);
}

如果我們想象Animal的子類型,例如Dog ,我們就不能將此方法與Dog列表一起使用,即使Dog是Animal的子類型。我們可以使用通配符來做到這一點。

public static void printAnimals(List<? extends Animal> animals) {
    ...
}

現在,此方法適用于Animal類型及其所有子類型

printAnimals(
    Arrays.asList(
        new Cat("Jim", "brown", 2),
        new Dog("Rocky", "black", 5)
    )
);

這稱為上限通配符,其中Animal類型是上限。

2??下界通配符

我們還可以指定具有下限的通配符,其中未知類型必須是指定類型的超類型可以使用super 關鍵字后跟特定類型來指定下限。

例子:

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

通用方法

想象一下,我們需要一種采用不同數據類型并執行某些操作的方法。我們可以為此創建一個通用方法并重用它。

public static <T> void call(T data) {
    System.out.println(data);
}

call("hello");
call(45);
call(15.67);
call(5L);
call(new Dog("Rocky", "black", 5));

/* output:
    hello
    45
    15.67
    5
    generics.Dog@62294cd9
*/ 

如果我們想返回數據而不是 VOID,我們也可以這樣做。

public static <T> T getData(T data) {
    return data;
}

System.out.println(getData("Test"));   // 輸出 Test

我們也可以在通用方法中接受多種數據類型。

public static <T, V> void getMultiData(T data1, V data2) {
    System.out.println("data 1: " + data1);
    System.out.println("data 2: " + data2);
}

getMultiData(50, "Shades of Grey");

好了,今天的分享就到這里,如果各位覺得老七的文章還不錯的話,麻煩大家動動小手,

分享到:
標簽:Java
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定