Java初识泛型

news2025/2/28 5:17:22
  1. 什么是泛型
    泛型是jdk1.5引入的新语法,泛型就是适用于许多许多类型,就是对类型实现了参数化
  2. 实现一个类,类中包含一个数据成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中某个下标的值
class MyArray {
    public Object[] obj;
//此时存储数据的时候,什么类型都可以存储
//此时获取数据的时候,必须强转
//思考:能不能指定放啥类型,这样就不要强转了——在类的后面加<>,并指定类型
    public MyArray() {
        obj = new Object[10];
    }

    public void setValue(int pos, Object value) {
        obj[pos] = value;
    }

    public Object getValue(int pos) {
        return obj[pos];
    }

}


public class Test {
    public static void main(String[] args) {
        MyArray myArray = new MyArray();
        myArray.setValue(1,12);
        myArray.setValue(0,"123");

        int a = (int)myArray.getValue(1);
    }
}

这样写:
①此时存储数据的时候,什么数据都可以存储【比如int类型和String类型都可以存进去】

        myArray.setValue(1,12);
        myArray.setValue(0,"123");

②此时获取数据的时候,必须强制类型转换

        int a = (int)myArray.getValue(1);

思考:能不能指定放啥类型,然后就不需要强制类型转换了呢?——泛型!!!

(虽然此时当前数组可以存放任何数据,但是我们还是希望数组只能持有一种数据类型,而不是同时持有这么多类型)所以,泛型的主要目的是:指定当前容器要持有什么类型的对象,让编译器去做检查。把类型作为参数传递,需要什么类型,就传入什么类型。

  1. 将上述程序修改成泛型类
class MyArray<E> {
    public E[] obj = (E[]) new Object[10];

    public void setValue(int pos, E value) {
        obj[pos] = value;
    }

    public E getValue(int pos) {
        return obj[pos];
    }

}


public class Test {
    public static void main(String[] args) {
        MyArray<Integer> myArray = new MyArray<>();
        myArray.setValue(0,1);
        int a = myArray.getValue(0);
        System.out.println(a);
    }
}

①此时只有指定的数据类型才可以存储

        MyArray<Integer> myArray = new MyArray<>();
        myArray.setValue(0,1);
        myArray.setValue(1,"abc0");//报错

因为此时在实例化对象的同时,指定了当前泛型类的指定参数类型是Integer【并且中鼎的参数类型必须是引用类型,放int就错了,int是基本数据类型】
②此时获取0下标存放的值没有发生强制类型转换

        int a = myArray.getValue(0);
        System.out.println(a);

但是这里发生了自动装箱和拆箱操作。

因此,泛型的好处/意义:
1.存储数据的时候,可以帮我们进行自动的类型检查
2.获取元素的时候,可以帮我们进行类型转换
【注意以上2个好处/意义都是发生在编译的时候,泛型是编译时期的一种机制,在运行的时候没有泛型的概念。】

  1. 泛型的语法
    ①定义泛型类
class 泛型类名称<类型形参列表>{

}

注意:
1、类名后的<>,比如代表占位符,表示当前类是一个泛型类,只相当于一个形参,实参是在实例化泛型类的时候给的。
2、不能new泛型类型的数组
规定:泛型当中不能去实例化一个泛型类型数组

T[] t = new T[5]; //不能实例化泛型数组

T[] t = (T[])new Object[5]; //对的,实例化Object类型数组,并且强制类型转换成泛型,但是不是足够好


//这种方法是最好的
Object[] obj = new Object[5]; //还是new Object对象
public T getPos(int pos) {
	return (T)obj[pos];  //在getset中再强转成T类型


②实例化泛型类对象

	MyArray<Integer> list = new MyArray<Integer>();
	泛型类<类型实参> 变量名      泛型类<类型实参>(构造方法实参)

注意:泛型只能接受类,类型实参所有的基本数据类型必须使用包装类。
关于省略类型实参:当编译器可以根据上下文推导的时候可以省略new后面的那个泛型实参

	MyArray<Integer> list = new MyArray();//可以推导出实例化需要的类型实参为Integer

③裸类型(左右两边的实参都省略了)
裸类型是一个泛型类但是没有带类型实参。

MyArray list = new MyArray();

理论上应该要报错,但是这里牵扯到Java的历史原因,裸类型是为了兼容老版本的API保留的机制。

  1. 泛型再Java中是怎么编译的?——擦除机制
    查看泛型程序的字节码文件
    在这里插入图片描述
    可以发现,在编译的过程中,将所有的E都替换成了Object,这种机制也叫擦除机制。
    擦除机制:运行的时候没有泛型,编译完成之后,泛型类型被擦除为Object类型,也就是说编译好之后E其实是一个Object。
    Java的泛型机制是在编译级别实现的,编译器生成的字节码在运行期间不包含泛型的类型信息。
    那么泛型只存在在编译的时候,并且在这个时候干了2件伟大而具有意义的事:【这也是和直接写Object的区别,泛型的好处】
    ①检查:检查是不是要的类型
    ②转换:去除了强制类型转换

  2. 泛型的上界
    泛型如果没有边界的话,都变成了Objetct。因此有时需要对传入的类型变量做一定的约束,通过类型边界来约束。(用到extends)
    ① 泛型的上界是类
    <E extends Number>
    代表E是Number的子类,或者E是Number本身

class A<T extends Number> {
    public T[] obj = (T[])new Object[10];
}
public class Test {
    A<Integer> a1 = new A<>();
    A<Double> a2 = new A<>();
    A<String> a3 = new A<>();  //报错
}

如代码A<String> a3 = new A<>(); 会编译错误,因为String不是Number的子类类型。

②泛型的上界是接口
<E extends Comparable<E>>
代表将来指定的参数E类型一定要实现了Comparable这个接口

class AA<E extends Comparable<E>> {

}

class BB {

}

public class demo {
    AA<Integer> a1 = new AA<>();//不报错,因为Integer里面实现了Comparable接口
    AA<BB> a2 = new AA<>();//报错,因为BB类没有实现Comparable接口
}

代码AA<BB> a2 = new AA<>();会编译错误,因为BB类没有实现Comparable接口,但是Integer不会,因为Integer包装类实现了Comparable接口。
在这里插入图片描述
7. 泛型也可以用在方法中
在返回值类型前加<>类型参数列表

    public <E>void swap(E[] array, int i, int j) {
        E tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }

静态方法的泛型,需要在static后面<>声明泛型类型参数

    public static <E> void swap(E[] array, int i, int j) {
        E tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }

关于调用泛型方法:
使用类型推导和不使用类型推导

    public static void main(String[] args) {
        Test test = new Test();
        Integer[] array = {1,2,3};
        test.swap(array,1,2); //使用类型推导
        test.<Integer>swap(array,0,1);//使用类型推导
    }

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux-免费ssl证书

title: linux-免费ssl证书 categories: Linux tags: [linux, xshell] date: 2022-09-10 19:29:55 comments: false mathjax: true toc: true linux-免费ssl证书 前篇 33种免费获取SSL证书的方式 - https://zhuanlan.zhihu.com/p/174755007 HTTPS 证书文件格式转换 HTTPS证书文…

基于多目标粒子群优化算法的冷热电联供型综合能源系统运行优化附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

acm退役小记

本人大学是接近一本线的二本大学&#xff0c;目前能打的区域赛场基本打完了&#xff0c;桂林rank105和沈阳rank140是有两个区域赛铜。如果我是强校的话&#xff0c;也会说下只能拿废物铜耻辱退役 这里简单记下我的acm生涯 其实我一直觉得对于我们这种弱校&#xff0c;虽然打a…

delete删除后怎么恢复文件?四种方法进行找回

演示机型&#xff1a;技嘉 H310M HD22.0 系统版本&#xff1a;Windows 10 专业版 很多小伙伴在日常工作或生活中&#xff0c;喜欢通过delete键进行删除文件&#xff0c;虽然这种删除方式快捷方便&#xff0c;但是也容易出现误删的情况&#xff0c;那么用delete键删除的文件可以…

【语音识别】高斯混合模型(GMM)说话人识别【含Matlab源码 574期】

⛄一、高斯混合模型简介 GMM基本框架 类似的还有GMM-UBM(Universal background model)算法&#xff0c;其与GMM的区别在于&#xff1a;对L类整体样本训练一个大的GMM&#xff0c;而不像GMM对每一类训练一个GMM模型。SVM的话MFCC作为特征&#xff0c;每一帧作为一个样本&#…

golang的new和make

golang 变量定义的方式 可以通过 var变量名称变量类型 进行声明变量&#xff0c;当我们没有给它赋值的时候&#xff0c;它们的结果是变量类型的零值&#xff0c;例如&#xff1a; string 的零值是"",int 的零值是0&#xff0c;引用类型的零值是nil。 前面两种类型…

Android加载第三方so库

本篇文章使用的android studio版本是:Android Studio Bumblebee | 2021.1.1 Patch 2 上一篇文章&#xff1a;Android开发java调用C简单示例 演示了java调C&#xff0c;那么so文件能否复用到别的项目了&#xff1f; 这次我们尝试用上一篇文章生成的so库&#xff0c;调用里面的…

APK 签名 v1 v2 步骤

APK 签名 v1 v2 步骤 需要工具 **apksigner.jar jarsinger.exe keytool.exe zipalign.exe ** 1.生成 keystore keytool -genkey -v -keystore my.keystore -alias liuhan -keyalg RSA -keysize 2048 -sigalg SHA256withRSA -dname "cnTest,ouTest,cCA" -validity …

【机器学习入门项目10例】(六):KMeans聚类

💥 项目专栏:【机器学习入门项目10例】 文章目录 一、KMeans聚类二、数据集介绍三、KMeans聚类算法介绍四、定义KMeans模型4.1 kmeans算法入口4.2 初始化簇4.3 计算DBI优化指标4.4 计算每个样本到簇中心的距离4.5 更新每个样本所属的簇分类4.6 更新每个簇的中心4.7 官方实现…

百行代码实现VLC简易视频播放器【详细环境配置过程+可执行源码注释完整】

文章目录❓什么是VLC&#x1f680;VLC 库的集成⭐VLC环境配置演示【win10系统vs2017win64】&#x1f34e;VLC 库的基本使用&#x1f382;视频播放器实现⭐自定义函数Unicode2Utf8讲解&#x1f3e0;总结❓什么是VLC VLC 是 Video Lan Client 的缩写&#xff0c;原先是几个法国的…

学生HTML网页作业作品:HTML+CSS网站设计与实现【红色喜庆邀请函 3页】

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

朗道-西格尔零点猜想(the Landau-Siegel Zeros Conjecture)

1 简介 朗道-西格尔零点猜想&#xff08;the Landau-Siegel Zeros Conjecture&#xff09;&#xff0c;是一个数学难题。 要理解朗道-西格尔零点猜想&#xff0c;首先需要理解黎曼猜想&#xff0c;进而需理解广义黎曼猜想&#xff0c;以及狄利克雷L函数。断言L函数没有异常零…

【OneDrive篇】OneDrive禁用个人保管库(网页端)

【OneDrive篇】OneDrive禁用"个人保管库"&#xff08;网页端&#xff09; 最近OneDrive个人保管库一直同步出错&#xff0c;把文件全部移出来还是一样&#xff0c;就选择直接禁用"个人保管库"功能了—【蘇小沐】 文章目录【OneDrive篇】OneDrive禁用"…

Windowns编译OpenSSL

前言 开发过程中需要上传数据&#xff0c;URL是https的&#xff0c;Qt默认是http网络请求&#xff0c;访问https需要用到SSL认证&#xff0c;而Qt默认不支持&#xff0c;需要自己编译OpenSSL库。 一、下载OpenSSL 环境&#xff1a;Qt 5.12.2 MSVC 2017,32bit ,可通过下面代码…

[附源码]Python计算机毕业设计高校国防教育管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

关于webpack(v5.74.0)的钩子在插件中的应用

常用监听钩子 compiler 钩子 compiler.hooks.entryOption 在 webpack 选项中的 entry 被处理过之后调用。一般用来获取入口。 compiler.hooks.compile beforeCompile 之后立即调用&#xff0c;但在一个新的 compilation 创建之前。这个钩子 不会 被复制到子编译器。能获取…

C++智能指针之shared_ptr

C智能指针之shared_ptr前言一、Shared_ptr1.1 shared_ptr类的操作1.2 make_shared函数1.3 shared_ptr的拷贝赋值1.4 shared_ptr的自动销毁对象内存机制1.5 使用动态生存期的资源的类1.6 shared_ptr与new结合使用1.7 不要混合使用普通/智能指针1.8 不要使用 get 初始化另一个智能…

Keras深度学习实战(38)——图像字幕生成

Keras深度学习实战&#xff08;38&#xff09;——图像字幕生成0. 前言1. 模型与数据集分析1.1 数据集分析1.2 模型分析2. 实现图像字幕生成模型2.1 数据集加载与预处理2.2 模型构建与训练3. 使用束搜索生成字幕3.1 束搜索原理3.2 利用束搜索改进预测结果小结系列链接0. 前言 …

Springboot——Controller层开发、请求与响应、RESTful开发规范

目录 一、入门案例&#xff08;小了解&#xff0c;没啥用&#xff09; 1.1 创建Springboot工程 1.2 导入maven坐标 1.3 controller层代码 1.4 postman测试 二、 REST常用注解 2.1 Controller 2.2 RequestMapping&#xff08;请求映射路径&#xff09; 2.3 Response…

Python学习基础笔记十三——函数

1、函数的定义&#xff1a; 函数是一段具有特定功能的、可重用的语句组。 说明&#xff1a;过程语言&#xff0c;程序员是按照顺序一行一行的编写代码&#xff0c;然后是顺序执行&#xff0c;很容易出现大量重复的代码行&#xff0c;那么有人就考虑将相同的代码提取出来&…