Java——泛型

在这里插入图片描述

前言:
泛型类,泛型方法,泛型接口,通配符,类型擦除


文章目录

  • 一、 泛型
    • 1.1、泛型的基本概念
    • 1.2 泛型的使用
  • 三、通配符(Wildcard)
  • 四、类型擦除(Type Erasure)
  • 五、泛型的局限性

一、 泛型

Java泛型(Java Generics)是一种允许类、接口和方法操作不同数据类型而无需指定具体数据类型的机制。Java引入泛型是为了提供更高的类型安全性、可读性、可维护性和代码复用性,这在Java 5及以后版本中引入。

1.1、泛型的基本概念

  1. 泛型类
    泛型类是指在类声明时带有一个或多个类型参数的类。这些类型参数在类的使用过程中被具体化。定义泛型类时,使用尖括号<>括起来的类型参数。

    public class Box<T> {private T content;public void set(T content) {this.content = content;}public T get() {return content;}
    }
    

    在上述例子中,T是一个类型参数,可以在使用时被具体化为任何类型。

  2. 泛型接口
    泛型接口和泛型类类似,只是定义在接口上。

    public interface Container<T> {void add(T item);T remove();
    }
    
  3. 泛型方法
    泛型方法是在方法声明中引入一个或多个类型参数的方法。这些类型参数使方法可以独立于任何特定的类型工作。

    public class Util {public static <T> boolean compare(T t1, T t2) {return t1.equals(t2);}
    }
    

    在这个例子中,<T>是在方法声明中引入的类型参数,可以在方法的参数列表和返回类型中使用。

注意,泛型方法和泛型类中的普通方法有以下区别:

  1. 类型参数的定义位置不同

    • 泛型方法:类型参数是在方法声明中定义的,方法可以在其签名中使用这些类型参数。
    • 类中的普通方法:如果类是泛型类,那么普通方法可以使用类的类型参数,但不能定义自己的类型参数。
  2. 泛型方法的灵活性

    • 泛型方法:可以在非泛型类中定义,也可以在泛型类中定义。每个方法可以有自己独立的类型参数。
    • 类中的普通方法:只能使用类级别的类型参数(如果类是泛型类)。

在泛型类中定义泛型方法的示例
在泛型类中也可以定义泛型方法,且方法可以有不同的类型参数:

public class Box<T> {private T content;public void set(T content) {this.content = content;}public T get() {return content;}// 泛型方法,使用独立的类型参数 Upublic <U> void print(U item) {System.out.println(item);}
}

1.2 泛型的使用

  1. 泛型类的使用
    在实例化泛型类时,需要为类型参数提供具体的类型。

    Box<String> stringBox = new Box<>();
    stringBox.set("Hello");
    String content = stringBox.get();
    System.out.println(content);
    
  2. 泛型方法的使用
    调用泛型方法时,可以显式指定类型参数,也可以让编译器通过类型推断自动确定类型参数。

    String s1 = "test";
    String s2 = "test";
    boolean result = Util.<String>compare(s1, s2); // 显式指定类型参数
    boolean result2 = Util.compare(s1, s2); // 通过类型推断
    
  3. 泛型接口的使用
    实现泛型接口时,可以指定接口的类型参数。

    public interface Container<T> {void add(T item);T remove();
    }// 实现泛型接口时具体化类型参数为 String
    public class StringContainer implements Container<String> {private List<String> items = new ArrayList<>();@Overridepublic void add(String item) {items.add(item);}@Overridepublic String remove() {return items.isEmpty() ? null : items.remove(0);}
    }
    

    或者实现类保留类型参数

    public interface Container<T> {void add(T item);T remove();
    }// 让实现类保留类型参数
    public class GenericContainer<T> implements Container<T> {private List<T> items = new ArrayList<>();@Overridepublic void add(T item) {items.add(item);}@Overridepublic T remove() {return items.isEmpty() ? null : items.remove(0);}
    }
    

三、通配符(Wildcard)

  1. 无界通配符
    <?> 表示任何类型。这在需要表示不确定的类型时很有用。

    public void printList(List<?> list) {for (Object obj : list) {System.out.println(obj);}
    }
    
  2. 上界通配符
    <? extends T> 表示类型是 TT 的子类。

    public void processElements(List<? extends Number> list) {for (Number num : list) {System.out.println(num);}
    }
    
  3. 下界通配符
    <? super T> 表示类型是 TT 的父类。

    public void addNumbers(List<? super Integer> list) {list.add(1);list.add(2);list.add(3);
    }
    

四、类型擦除(Type Erasure)

在Java中,泛型类型在编译时会被擦除,也就是Java编译器将泛型代码转换为非泛型代码,这意味着在运行时,泛型类型信息将不可用。这是为了向后兼容Java 5之前的版本。在类型擦除过程中:

  1. 泛型类型参数被替换为其上界(若未指定上界,则为Object)。
  2. 插入类型转换,以保证类型安全。
public class Box<T> {private T content;public void set(T content) {this.content = content;}public T get() {return content;}// 编译后,大致变成以下形式// private Object content;// public void set(Object content) { this.content = content; }// public Object get() { return content; }
}

五、泛型的局限性

尽管泛型提供了很多好处,但它也有一些限制:

  1. 不能实例化泛型类型:因为类型擦除的存在,无法在运行时获取类型参数的具体类型。

    public class Box<T> {// 错误:不能实例化类型参数// private T content = new T();
    }
    
  2. 不能创建泛型数组:数组在运行时会保留类型信息,而泛型在运行时会被擦除。

    public class Box<T> {// 错误:不能创建泛型数组// T[] array = new T[10];
    }
    
  3. 不能使用基本类型作为类型参数:泛型只能用于引用类型。

    Box<int> intBox = new Box<>(); // 错误:不能使用基本类型作为类型参数
    Box<Integer> integerBox = new Box<>(); // 正确
    
  4. 不能在静态上下文中使用泛型类型参数:因为静态成员属于类,而不属于某个特定的对象。

    public class Box<T> {// 错误:静态字段不能使用类型参数// private static T content;
    }
    

在这里插入图片描述
如果你喜欢这篇文章,点赞👍+评论+关注⭐️哦!
欢迎大家提出疑问,以及不同的见解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/359874.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React Native性能优化红宝书

一、React Native介绍 React Native 是Facebook在React.js Conf2015 推出的开源框架&#xff0c;使用React和应用平台的原生功能来构建 Android 和 iOS 应用。通过 React Native&#xff0c;可以使用 JavaScript 来访问移动平台的 API&#xff0c;使用 React 组件来描述 UI 的…

ONLYOFFICE 文档 8.1 现已发布:功能全面的 PDF 编辑器、幻灯片版式等等

0、前言 在技术的快速发展和工作方式的持续演进下&#xff0c;现代办公软件正变得越来越强大和多样化。ONLYOFFICE&#xff0c;作为市场上备受瞩目的一体化办公解决方案&#xff0c;以其全面的文档编辑、表格处理和演示制作功能&#xff0c;满足了用户在不同办公场景下的需求。…

安卓设备优雅的命令 adb 以及 优秀的控制 scrcpy

一、背景 如果有多台安卓设备&#xff0c;并为这些设备安装软件&#xff0c;一个个使用u盘再加上鼠标操作虽然可以做到&#xff0c;但是大概率比较麻烦。试想下&#xff0c;如果坐在电脑旁边&#xff0c;就能鼠标在电脑上点点就能解决问题&#xff0c;是多么优雅的一件事情。 …

使用上海云盾 CDN 和 CloudFlare 后 Nginx、 WordPress、 Typecho 获取访客真实 IP 方法

最近因为被 DDoS/CC 攻击的厉害,明月就临时的迁移了服务器,原来的服务器就空置下来了,让明月有时间对服务器进行了重置重新部署安装生产环境。因为站点同时使用了上海云盾和 CloudFlare(具体思路可以参考【国内网站使用国外 CloudFlare CDN 的思路分享】一文)两个 CDN 服务…

Docker--基础详解

目录 Docker介绍 Docker与传统虚拟机相比的优势 Docker基础插件 Docker镜像 容器和仓库 Docker介绍 Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言开发&#xff0c;遵从Apache2.0开源协议&#xff0c;依赖Linux内核的Cgroup和Namespace等技术&#xff0c;对进…

快速欧氏聚类与普通欧氏聚类比较

1、前言 文献《FEC: Fast Euclidean Clustering for Point Cloud Segmentation》介绍了一种快速欧氏聚类方法,大概原理可以参考如下图,具体原理可以参考参考文献。 2、时间效率比较:快速欧氏聚类VS普通欧氏聚类 网上搜集的快速欧式聚类,与自己手写的普通欧式聚类进行对比,…

“了解MySQL中的enum枚举数据类型“

目录 # 开篇 1. 创建包含枚举类型的表 2. 插入枚举类型的数据 3. 查询包含枚举类型的表 4. 更新枚举类型的数据 5. 使用枚举类型的好处 注意事项 示例总结 附加 # 开篇 在数据库中&#xff0c;枚举&#xff08;ENUM&#xff09;是一种数据类型&#xff0c;用于存储一组…

uniapp中Error: project.configjson: libVersion 字段需为 string. string

错误如下 找到manifestjson文件到源码视图 添加这段代码"libVersion": "latest",即可

【WEB前端2024】3D智体编程:乔布斯3D纪念馆-第46课-使用json文件

【WEB前端2024】3D智体编程&#xff1a;乔布斯3D纪念馆-第45课-使用头像 使用dtns.network德塔世界&#xff08;开源的智体世界引擎&#xff09;&#xff0c;策划和设计《乔布斯超大型的开源3D纪念馆》的系列教程。dtns.network是一款主要由JavaScript编写的智体世界引擎&…

在Maven工程中手动配置并测试SpringBoot(巨详)

本篇博客承继自博客&#xff1a; 在IDEA 2024.1.3 (Community Edition)中创建Maven项目_idea2024.1.3如何创建maven项目-CSDN博客 配置POM文件 打开工程中的pom.xml文件&#xff0c;先向其中写入 <parent><groupId>org.springframework.boot</groupId><…

【挑战100天首通《谷粒商城》】-【第一天】06、环境-使用vagrant快速创建linux虚拟机

文章目录 课程介绍1、安装 linux 虚拟机2、安装 VirtualBoxStage 1&#xff1a;开启CPU虚拟化Stage 2&#xff1a;下载 VirtualBoxStage 2&#xff1a;安装 VirtualBoxStage 4&#xff1a;安装 VagrantStage 4-1&#xff1a;Vagrant 下载Stage 4-2&#xff1a;Vagrant 安装Stag…

[职场] 线上面试的准备工作 #知识分享#经验分享#媒体

线上面试的准备工作 面对求职中的面试&#xff0c;应届毕业生该做些什么准备呢&#xff1f;在这里&#xff0c;向各位分享面试前做好预案不慌张几点准备。现在许多面试是通过线上形式进行的。对于求职者来说&#xff0c;要做好两手准备。在这里&#xff0c;重点与大家分享线上面…

Qt画实时曲线图

Qt引入QcustomPlot 首先下载QcustomPlot源代码&#xff0c;https://github.com/qcustomplot/qcustomplot 下载zip文件 运行所下载的项目生成库文件libqcustomplotd2.a文件和qcustomplotd2.dll文件。 在项目中添加printsupport。 并将qcustomplot.h文件和qcustomplot.cpp文…

基于matlab的图像二值化

1 原理 图像二值化的原理是将彩色或灰度图像转换为只包含两种颜色&#xff08;通常是黑色和白色&#xff09;的二值图像的过程。其关键是通过设定一个阈值&#xff0c;将图像中的像素点的灰度值与阈值进行比较&#xff0c;根据比较结果将像素点设置为白色或黑色。步骤如下&…

ElementPlus组件与图标按需自动引入

按需自动引入组件 1. 安装ElementPlus和自动导入ElementPlus组件的插件 pnpm install element-plus pnpm install -D unplugin-vue-components unplugin-auto-import 2. vite.config.ts进行修改 import { defineConfig } from vite import vue from vitejs/plugin-vue // …

2024CICE电博会·以“链主”企业为核心,推动产业链协同发展

随着全球科技日新月异的发展&#xff0c;消费电子产业已成为推动经济增长、改善人民生活的重要力量。中国国际消费电子博览会&#xff08;简称CICE电博会&#xff09;自2001年创办以来&#xff0c;已经走过了二十余个春秋&#xff0c;凭借其独特的地理位置优势、专业的组织策划…

如何开发、使用 Starter

开发 第一步&#xff1a;创建starter工程hello-spring-boot-starter并配置pom.xml文件 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchem…

趣味C语言——【猜数字】小游戏

&#x1f970;欢迎关注 轻松拿捏C语言系列&#xff0c;来和 小哇 一起进步&#xff01;✊ &#x1f389;创作不易&#xff0c;请多多支持&#x1f389; &#x1f308;感谢大家的阅读、点赞、收藏和关注&#x1f495; &#x1f339;如有问题&#xff0c;欢迎指正 感谢 目录 代码…

BP神经网络-入门到理解-长文讲述

本文来自&#xff1a;老饼讲解-BP神经网络 https://www.bbbdata.com 目录 一、BP神经网络的仿生意义 二、BP神经网络的结构 三、BP神经网络的前馈与后馈 3.1 BP神经网络的前馈 3.2 什么是BP神经网络的后馈 四、BP神经网络的训练 4.1 BP神经网络归一化 4.2 梯度下降算法…

使用SpringCache实现Redis缓存

目录 一 什么是Spring Cache 二 Spring Cache 各注解作用 ①EnableCaching ②Cacheable ③CachePut ④CacheEvict 三实现步骤 ①导入spring cache依赖和Redis依赖 ②配置Redis连接信息 ③在启动类上加上开启spring cache的注解 ④ 在对应的方法上加上需要的注解 一 什么…