当前位置:首页 > 科技  > 软件

Java中的泛型,看完这个还不会,我倒立洗头!

来源: 责编: 时间:2023-11-08 09:10:41 144观看
导读我今天聊聊Java中的泛型, 它是一个广泛使用但讨论较少的主题。我们经常会使用它,但大多数开发人员并没有真正了解它。Java开发中你们肯定都用过List或者ArrayList。那你们应该记得如何定义他们吧?List<Integer> list = n

oFI28资讯网——每日最新资讯28at.com

我今天聊聊Java中的泛型, 它是一个广泛使用但讨论较少的主题。我们经常会使用它,但大多数开发人员并没有真正了解它。oFI28资讯网——每日最新资讯28at.com

Java开发中你们肯定都用过List或者ArrayList。那你们应该记得如何定义他们吧?oFI28资讯网——每日最新资讯28at.com

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

这就是我们声明的方式。所以,我们使用了泛型。这里,<Integer>是我们传递的指定类型。那是一个类型。在我们创建这样的列表后,您只能将整数添加到列表中。oFI28资讯网——每日最新资讯28at.com

那如果我们不指定类型呢?oFI28资讯网——每日最新资讯28at.com

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

如果我们像上面这样定义列表,我们就可以将从 Object 超类扩展的任何类型的数据添加到列表中。oFI28资讯网——每日最新资讯28at.com

所以添加泛型后,我们可以实现此列表的类型安全。oFI28资讯网——每日最新资讯28at.com

泛型意味着参数化类型。Java 让我们创建一个类、接口和方法,可以在泛型域中与不同类型的数据(对象)一起使用。oFI28资讯网——每日最新资讯28at.com

泛型的优点是:oFI28资讯网——每日最新资讯28at.com

  • 代码可重用性——我们可以使用具有多种对象类型的通用代码
  • 编译时类型检查——Java 将在编译时检查泛型代码是否有错误
  • 类型安全——我们可以限制添加不必要的数据
  • 集合中的用法——集合需要对象类型来处理数据

让我们举个例子来解释为什么我们需要泛型。oFI28资讯网——每日最新资讯28at.com

想象一下,您必须使用打印机类打印数字和文本。打印机有一种在创建数据时接受数据的方法。oFI28资讯网——每日最新资讯28at.com

在传统方式中,我们必须创建 2 个类,因为我们有 2 种数据类型:数字(整数)和文本(字符串)oFI28资讯网——每日最新资讯28at.com

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);    }}

使用:oFI28资讯网——每日最新资讯28at.com

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    }}

没有觉得代码重复了?唯一的区别就是数据类型不同!oFI28资讯网——每日最新资讯28at.com

下面我们利用泛型来改造一下,使它成为一个通用的类型。oFI28资讯网——每日最新资讯28at.com

public class Printer<T> {    private final T data;    public Printer(T data) {        this.data = data;    }    public void print() {        System.out.println("print::: " + data);    }}

使用:oFI28资讯网——每日最新资讯28at.com

Printer<Integer> integerPrinter = new Printer<>(5);integerPrinter.print();   // 输出 print::: 5Printer<String> stringPrinter = new Printer<>("Hello");stringPrinter.print();   // 输出 print::: HelloPrinter<Double> doublePrinter = new Printer<>(45.34);doublePrinter.print();   // 输出 print::: 45.34Printer<Long> longPrinter = new Printer<>(5L);longPrinter.print();z    //输出 print::: 5

现在我们就只写了一个类,T用来表示作为通用标准的类型。我们甚至可以为其他数据类型(例如 Double/Long)创建打印对象。代码可重用性是通过风格实现的。oFI28资讯网——每日最新资讯28at.com

我们还可以创建多个类型的通用类。如下:oFI28资讯网——每日最新资讯28at.com

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 类型命名约定:oFI28资讯网——每日最新资讯28at.com

  • E - 元素(用于集合)
  • K — 键(在地图中使用)
  • N——数字
  • T——类型
  • V - 值(在地图中使用)
  • S、U、V 等 — 第二、第三、第四类型

有界泛型

这是泛型的高级版本。我们可以通过有界泛型来限制更多并实现更多类型安全。oFI28资讯网——每日最新资讯28at.com

假设我们有一个AnimalPrinter类,它只能打印动物详细信息。不允许与其他物体一起使用。如何实现这一目标?oFI28资讯网——每日最新资讯28at.com

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 部分完成了工作!我们限制了狗和猫的通用性!oFI28资讯网——每日最新资讯28at.com

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

多重界限

假设我们想向打印机通用功能添加更多功能。我们可以这样实现。oFI28资讯网——每日最新资讯28at.com

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

我使用 Serialized 接口提供了 Serialized 功能。这里有一些重要的事情需要记住。oFI28资讯网——每日最新资讯28at.com

  • 我们必须在子类(Cat 和 Dog)中实现接口。
  • 类应该放在第一位,然后是 & 和接口。
  • 由于 Java 不支持多重继承,因此只能扩展 1 个类。

泛型通配符

通配符由问号?表示 在 Java 中,我们用它们来指代未知类型。这可以用作泛型的参数类型。然后它将接受任何类型。在下面的代码中,我使用通配符将任何对象的列表用作方法参数。oFI28资讯网——每日最新资讯28at.com

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]

列表现在可以是任何类型!oFI28资讯网——每日最新资讯28at.com

上限通配符

考虑这个例子:oFI28资讯网——每日最新资讯28at.com

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

如果我们想象Animal的子类型,例如Dog ,我们就不能将此方法与Dog列表一起使用,即使Dog是Animal的子类型。我们可以使用通配符来做到这一点。oFI28资讯网——每日最新资讯28at.com

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

在,此方法适用于Animal类型及其所有子类型。oFI28资讯网——每日最新资讯28at.com

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

这称为上限通配符,其中Animal类型是上限。oFI28资讯网——每日最新资讯28at.com

下界通配符

我们还可以指定具有下限的通配符,其中未知类型必须是指定类型的超类型。可以使用super 关键字后跟特定类型来指定下限。oFI28资讯网——每日最新资讯28at.com

例子:oFI28资讯网——每日最新资讯28at.com

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

通用方法

想象一下,我们需要一种采用不同数据类型并执行某些操作的方法。我们可以为此创建一个通用方法并重用它。oFI28资讯网——每日最新资讯28at.com

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,我们也可以这样做。oFI28资讯网——每日最新资讯28at.com

public static <T> T getData(T data) {    return data;}System.out.println(getData("Test"));   // 输出 Test

我们也可以在通用方法中接受多种数据类型。oFI28资讯网——每日最新资讯28at.com

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");

本文链接:http://www.28at.com/showinfo-26-17651-0.htmlJava中的泛型,看完这个还不会,我倒立洗头!

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 必读!SpringBoot接口参数校验N种实用技巧大揭秘

下一篇: 告别Node.js版本困扰,轻松切换开发环境!

标签:
  • 热门焦点
  • 直屏旗舰来了 iQOO 12和K70 Pro同台竞技

    直屏旗舰来了 iQOO 12和K70 Pro同台竞技

    旗舰机基本上使用的都是双曲面屏幕,这就让很多喜欢直屏的爱好者在苦等一款直屏旗舰,这次,你们等到了。据博主数码闲聊站带来的最新爆料称,Redmi下代旗舰K70 Pro和iQOO 12两款手
  • 红魔电竞平板评测:大屏幕硬实力

    红魔电竞平板评测:大屏幕硬实力

    前言:三年的疫情因为要上网课的原因激活了平板市场,如今网课的时代已经过去,大家的生活都恢复到了正轨,这也就意味着,真正考验平板电脑生存的环境来了。也就是面对着这种残酷的
  • 5月iOS设备性能榜:M1 M2依旧是榜单前五

    5月iOS设备性能榜:M1 M2依旧是榜单前五

    和上个月一样,没有新品发布的iOS设备性能榜的上榜设备并没有什么更替,仅仅只有跑分变化而产生的排名变动,刚刚开始的苹果WWDC2023,推出的产品也依旧是新款Mac Pro、新款Mac Stu
  • 十个简单但很有用的Python装饰器

    十个简单但很有用的Python装饰器

    装饰器(Decorators)是Python中一种强大而灵活的功能,用于修改或增强函数或类的行为。装饰器本质上是一个函数,它接受另一个函数或类作为参数,并返回一个新的函数或类。它们通常用
  • 一篇文章带你了解 CSS 属性选择器

    一篇文章带你了解 CSS 属性选择器

    属性选择器对带有指定属性的 HTML 元素设置样式。可以为拥有指定属性的 HTML 元素设置样式,而不仅限于 class 和 id 属性。一、了解属性选择器CSS属性选择器提供了一种简单而
  • 一个注解实现接口幂等,这样才优雅!

    一个注解实现接口幂等,这样才优雅!

    场景码猿慢病云管理系统中其实高并发的场景不是很多,没有必要每个接口都去考虑并发高的场景,比如添加住院患者的这个接口,具体的业务代码就不贴了,业务伪代码如下:图片上述代码有
  • OPPO、vivo、小米等国内厂商Q2在印度智能手机市场份额依旧高达55%

    OPPO、vivo、小米等国内厂商Q2在印度智能手机市场份额依旧高达55%

    7月20日消息,据外媒报道,研究机构的报告显示,在全球智能手机出货量同比仍在下滑的大背景下,印度这一有潜力的市场也未能幸免,出货量同比也有下滑,多家厂
  • 到手价3099元起!iQOO Neo8 Pro今日首销:安卓性能最强旗舰

    到手价3099元起!iQOO Neo8 Pro今日首销:安卓性能最强旗舰

    5月23日,iQOO如期举行了新品发布会,全新的iQOO Neo8系列也正式与大家见面,包含iQOO Neo8和iQOO Neo8 Pro两个版本,其中标准版搭载高通骁龙8+,而Pro版更
  • iQOO Neo8 Pro真机谍照曝光:天玑9200+和V1+旗舰双芯加持

    iQOO Neo8 Pro真机谍照曝光:天玑9200+和V1+旗舰双芯加持

    去年10月,iQOO推出了iQOO Neo7系列机型,不仅搭载了天玑9000+,而且是同价位唯一一款天玑9000+直屏旗舰,一经上市便受到了用户的广泛关注。在时隔半年后,
Top