简单了解泛型

基本数据类型和对应的包装类

在Java中, 基本数据类型不是继承自Object, 为了在泛型代码中可以支持基本类型, Java给每个基本类型都对应了一个包装类型.

简单来说就是让基本数据类型也能面向对象.基本数据类型可以使用很多方法, 这就必须让它变成类.

基本数据类型对定的包装类

基本数据类型       包装类

byte                      Byte

short                    Short

int                        Integer

long                     Long

float                     Float

double                 Double

char                    Character

boolean              Boolean

除了Integer 和 Character ,其余基本类型的包装类都是首字母大写

装包(箱)和拆包(箱)

把基本类型变为包装类型, 叫做装箱

把包装类型变为基本类型, 叫做拆箱

    public static void main(String[] args) {//自动装包, 内部其实是调用了 valueOf 方法来实现的Integer a = 10;int i = 99;Integer b = i;//基本类型 转变为 包装类型, 都是可以直接打印的System.out.println(a);System.out.println(b);//显示装箱Integer aa = Integer.valueOf(10);}
    public static void main(String[] args) {Integer a = 10;//自动拆箱, 内部调用了 intValue() 方法;int i = a;//拆包int aa = a.intValue();double b = a.doubleValue();}

Java 包装类提供了很多方法, 可以自动调用很方便

    public static void main(String[] args) {Integer a = 100;Integer b = 100;System.out.println(a == b);Integer a1 = 200;Integer b1 = 200;System.out.println(a1 == b1);}//代码上述的输出结果为: true   和    false

为什么呢?

如果出现这个错误第一时间想到了什么呢? 我想可以看一下 Integer 出现了什么错误, 然后呢? 在赋值的过程中出现了自动装箱, 自动装箱的函数是 valueOf , 所以可以在valueOf中寻找出错的点在哪里, 现在找到 valueOf 的源码, 看装包的过程哪一点出错了

    public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}

这个源码, 如果 i 在范围内就返回一个数组里面的值, 如果不在范围就返回 new Integer(i)

我们在源码中可以得到 low的大小为 -128, high 的大小为 127;

也就是 i 的范围在 -128 到 127 之间的话返回这个数组的某一个值

这个数组大小是多少呢? 范围是 [-128, 127], 共 256 个数字, 可以得出 下图 这个数组的样子

当 i 的范围在其之间可以返回相同的值, 如果超过了就返回一个 new 的值. 由此可出上述结果为什么是这样.

泛型

是Java中一种很难的语法

举个例子, 写一个类, 类包含一个数组成员, 让数组中可以存放任意类型的数据, 也能根据成员方法返回数组某个下标的值.

class MyArray {Object[] array = new Object[10];void setValue(int i, Object val) {array[i] = val;}Object getValue(int i) {return array[i];}
}
public class Main {public static void main(String[] args) {MyArray myArray = new MyArray();myArray.setValue(0, 1);myArray.setValue(1, "hello");//下面这一行代码报错, 因为返回值是 Object 类型,//需要强转为 String 类型才可以//String str = myArray.getValue(0);  <---报错String str = (String)myArray.getVlaue(0);}
}

这我们就想了, 不能让什么数据类型都能放到这个数组中, 我们可以指定一个数据, 这样我们在接受数据的时候也不用看每一个接收的数据是什么类型了. 我们就引入了泛型.

泛型的语法

1>

class 泛型类名称 <类型形参列表> {

    //可以使用类型参数

}

示例:

class ClassName<T1, T2, .... Tn>{

}

2>

class 泛型类名称<类型形参列表> extends 继承类 {

         //可以使用类型参数

}

示例:

class ClassName<T1, T2, .... Tn> extends ParentClass<T1> {

        //可以使用类型参数

}

类型形参列表可以用 T , E , K , V 等字母表示 其中<T, E, K, V...> 表示什么呢?

表示当前类 是一个泛型类 它只是一个占位符.

下面将上述代码改一下:

class MyArray <T>{Object[] array = new Object[10];void setValue(int i, T val) {array[i] = val;}T getValue(int i) {return (T)array[i]; // 把返回的类型,强转为指定类型}
}
public class Main {public static void main(String[] args) {//这行代码强制了数据类型为Integer, <>里面只能放入包装类MyArray<Integer> myArray = new MyArray<>();myArray.setValue(0, 1);//myArray.setValue(1, "hello");  <----当前代码报错了//如果我们想要放入其它类型的数据怎么做呢? 在创建一个新对象就好了MyArray<String> myArray1 = new MyArray<>();int i = myArray.getValue(0);System.out.println(i);}
}

 注意:

1> 因为使用了泛型, 在编译的时候 帮我们进行了类型的检查, 取数据也不需要进行类型转换

2> 在尖括号 <> 里面必须是引用类型.

3> 创建的一个数组的时候 不能写成 T[] array = new T[];

泛型的上界

语法:

class 泛型类名称  <类型形参 extends 类型边界>{

...

}

示例:

public class MyArray<T extends Number> {

...

}

其中的 T 必须是 Number 或者 Number的子类, 这就叫做泛型的上界

在创建对象时:

MyArray<Integer> a1 = new MyArray<>();   可以

MyArray<Double> a1 = new MyArray<>();   可以

MyArray<String> a1 = new MyArray<>();   不可以

举例: 写一个泛型类, 求一个数组中的最大值

class Alg<T> {public T findMaxValue(T[] array) {T max = array[0];for (int i = 1; i < array.length; i++) {if(max < array[i]) {max = array[i];}}return max;}
}

这段代码的 if 中的判断条件会出现报错, 为什么呢?

因为 T 是引用数据类型, 最终是被擦除为了 Object 类型, Object 没有实现了Comparable 接口, 所以不能直接比较大小, 要想能够比较大小, 就得让 T 实现 Comparable 接口, 实现了 Comparable接口后, 以后创建对象时, 只有实现了 Comparable 接口的才能创建

就比如: 

MyArray<Integer> a1 = new MyArray<>();   可以, 因为Integer 实现 Comparable 接口

class Preson { ... }

MyArray<Person> a1 = new MyArray<>();   不可以 , 因为Person 没有实现 Comparable 接口

所以上述代码应该写成:

class Alg<T extends Comparable> {public T findMaxValue(T[] array) {T max = array[0];for (int i = 1; i < array.length; i++) {if(max.compareTo(array[i]) < 0) {max = array[i];}}return max;}
}
public class Main {public static void main(String[] args) {Alg<Integer> alg = new Alg<>();Integer[] integers = {1, 2, 3, 4, 5, 6};Integer ret = alg.findMaxValue(integers);System.out.println(ret);}
}

写一个泛型方法:

如下列代码:

在这种情况下会出现 类型推导, 根据实参传值, 来推导出此时的类型.

class Alg2 {public <T extends Comparable>T findMaxValue(T[] array) {T max = array[0];for (int i = 1; i < array.length; i++) {if(max.compareTo(array[i]) < 0) {max = array[i];}}return max;}
}
public class Main {public static void main(String[] args) {Alg2 alg2 = new Alg2();Integer[] integers = {1, 2, 3, 4, 5, 6};Integer ret2 = alg2.findMaxValue(integers);System.out.println(ret2);}
}

下列代码将泛型方法改为静态的, 可以通过类名直接调用该泛型方法, 不用实例化对象了

class Alg3 {public static <T extends Comparable>T findMaxValue(T[] array) {T max = array[0];for (int i = 1; i < array.length; i++) {if(max.compareTo(array[i]) < 0) {max = array[i];}}return max;}
}public class Main {public static void main(String[] args) {Integer[] integers = {1, 2, 3, 4, 5, 6};Integer ret3 = Alg3.findMaxValue(integers);System.out.println(ret3);}
}

小结

学会泛型的含义, 泛型的目的, 泛型的语法

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

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

相关文章

[Linux][网络][TCP][四][流量控制][拥塞控制]详细讲解

目录 1.流量控制2.拥塞控制0.为什么要有拥塞控制&#xff0c;不是有流量控制么&#xff1f;1.什么是拥塞窗口&#xff1f;和发送窗口有什么关系呢&#xff1f;2.怎么知道当前网络是否出现了拥塞呢&#xff1f;3.拥塞控制有哪些算法&#xff1f;4.慢启动5.拥塞避免6.拥塞发生7.快…

LabelImg下载及目标检测数据标注

为什么这一部分内容这么少会单独拎出来呢&#xff0c;因为后期会接着介绍YOLOv8中的其他任务&#xff0c;会使用其他软件进行标注&#xff0c;所以就单独区分开来每一个任务的标注方式了。 这一部分就介绍目标检测任务的标注&#xff0c;数据集是我从COCO2017Val中抽出来两类&a…

矩阵相关运算1

矩阵运算是线性代数中的一个核心部分&#xff0c;它包含了许多不同类型的操作&#xff0c;可以应用于各种科学和工程问题中。 矩阵加法和减法 矩阵加法和减法需要两个矩阵具有相同的维度。操作是逐元素进行的&#xff1a; CAB or CA−B其中 A,B 和 C 是矩阵&#xff0c;且 C…

RTT PIN设备学习

获取GPIO编号 GET_PIN(port, pin)#define LED_BLUE_PIN GET_PIN(A, 0)设置引脚模式 void rt_pin_mode(rt_base_t pin, rt_base_t mode);设置引脚电平 void rt_pin_write(rt_base_t pin, rt_base_t value);rt_base_t pin 同上&#xff0c; 为引脚编号&#xff0c;尽量通过宏定…

新建的springBoot WEB项目无法自动返回html模版(gradle+kotlin版本)

最近研究了springBoot创建web项目&#xff0c; 第一步服务端返回字符串没有问题&#xff0c;第二步返回html时&#xff0c;还是返回的字符串。 文章目录 一、参考方案二、新建springBoot web项目三、启动项目的三种方式 一、参考方案 将控制器类的 RestController 改为 Contro…

代码随想录算法训练营第六十天| 647. 回文子串,516.最长回文子序列,动态规划总结篇

题目与题解 参考资料&#xff1a;动态规划总结篇 647. 回文子串 题目链接&#xff1a;647. 回文子串 代码随想录题解&#xff1a;647. 回文子串 视频讲解&#xff1a;动态规划&#xff0c;字符串性质决定了DP数组的定义 | LeetCode&#xff1a;647.回文子串_哔哩哔哩_bilibili …

【再探】设计模式—适配器、装饰及外观模式

结构型设计模式是用于设计对象和类之间关系的一组设计模式。一共有7种&#xff1a;适配器模式、装饰器模式、外观模式、桥接模式、组合模式、享元模式及代理模式。 1 适配器模式 需求&#xff1a;在软件维护阶段&#xff0c;已存在的方法与目标接口不匹配&#xff0c;需要个中…

每日一题5:Pandas-修改列

一、每日一题 一家公司决定增加员工的薪水。 编写一个解决方案&#xff0c;将每个员工的薪水乘以2来 修改 salary 列。 返回结果格式如下示例所示。 解答&#xff1a; import pandas as pddef modifySalaryColumn(employees: pd.DataFrame) -> pd.DataFrame:employees.loc[…

最后一块石头的重量 II ,目标和,一和0

最后一块石头的重量 II&#xff08;0-1背包问题 将石头尽可能分为两堆重量一样的&#xff0c;进行相撞则为0 class Solution {public int lastStoneWeightII(int[] stones) {int sum0;for(int x:stones){sumx;}int targetsum/2;int[] dpnew int[target1];//dp[j]表示最大石堆的…

【一起深度学习-----VGG】

VGG 原理图&#xff1a; 原理图&#xff1a; 为啥要使用VGG块呢&#xff1f; 对于AlexNet网络来说&#xff0c;虽然十分高效了&#xff0c;但是它并没有提供一个通用的模板&#xff0c;方便后续的研究。 故采用了模块化的思想&#xff0c;方便重复使用。 其实对比于AlexNet神经…

必应bing国内广告怎么做付费推广,提升产品曝光?

必应Bing作为微软旗下重要的搜索引擎平台&#xff0c;拥有着不可忽视的用户基础和市场潜力。对于寻求拓宽市场、提高品牌知名度的企业而言&#xff0c;利用必应Bing进行付费推广无疑是明智之选。通过必应Bing国内广告进行高效付费推广&#xff0c;助您轻松提升产品曝光度。 一…

C++:多态-虚函数

C 中的多态性是面向对象编程中的一个重要概念&#xff0c;它允许在运行时选择不同的函数实现&#xff0c;以适应不同类型的对象。 多态的种类 编译时多态性&#xff08;Compile-time Polymorphism&#xff09;&#xff1a;也称为静态多态性或早期绑定&#xff0c;指在编译时确…

【Git】Git学习-13:Gitee和GitLab的使用

学习视频链接&#xff1a;【GeekHour】一小时Git教程_哔哩哔哩_bilibili​编辑https://www.bilibili.com/video/BV1HM411377j/?vd_source95dda35ac10d1ae6785cc7006f365780 流程 1. 创建仓库/已有仓库 2. 克隆到本地/在远程仓库关联 git clone 仓库地址 git remote add 仓库别…

[Kotlin]创建一个私有包并使用

1.创建Kotlin项目 创建项目&#xff1a; 在Android Studio或其他IDE中选择“Create New Project”。选择Kotlin和Gradle作为项目类型和构建系统。指定项目名称和位置&#xff0c;完成设置。 添加依赖: 如果你的库需要额外的依赖&#xff0c;可以在 build.gradle (Module: app…

Axure中继器介绍以及案例分享

中继器是 Axure 中一个比较高阶的应用&#xff0c;它可以让我们在纯静态网页中模拟出类似带有后台数据交互的增删改查的效果。 一、中继器的基本使用方法&#xff1a; 整体流程分为三个步骤 ☆创建中继器 我们先在 Axured画布中拖入一个中继器元件 双击中继器后的效果 打开之…

APP 在华为应用市场上架 保姆级别详细流程

1、作为一名干开发的程序员&#xff0c;第一次能把自己的APP 上架&#xff0c;对自己来说是多么有意义的一项成就 2、创建一个 华为的开发者账号 根据提示填写完注册的信息https://developer.huawei.com/consumer/cn/product/华为开发者产品 | 开发者平台 | 流量变现 | 华为开…

商家制作微信小程序有什么好处?微信小程序的制作有哪些步骤和流程

微信小程序全面指南 微信小程序是微信生态系统中一项革命性的功能&#xff0c;为希望与庞大的微信用户群体互动的企业提供了独特的融合便捷性和功能性的体验。本全面指南深入探讨了微信小程序的世界&#xff0c;强调了其重要性、工作原理以及实际用例&#xff0c;特别是针对企…

CCE云原生混部场景下的测试案例

背景 企业的 IT 环境通常运行两大类进程&#xff0c;一类是在线服务&#xff0c;一类是离线作业。 在线任务&#xff1a;运行时间长&#xff0c;服务流量及资源利用率有潮汐特征&#xff0c;时延敏感&#xff0c;对服务SLA 要求高&#xff0c;如电商交易服务等。 离线任务&…

DOTA-Gly-Asp-Tyr-Met-Gly-Trp-Met-Asp-Phe-NH2,1306310-00-8,是一种重要的多肽化合物

一、试剂信息 名称&#xff1a;DOTA-Gly-Asp-Tyr-Met-Gly-Trp-Met-Asp-Phe-NH2CAS号&#xff1a;1306310-00-8结构式&#xff1a; 二、试剂内容 DOTA-Gly-Asp-Tyr-Met-Gly-Trp-Met-Asp-Phe-NH2是一种重要的多肽化合物&#xff0c;其CAS号为1306310-00-8。该多肽包含一个DO…

Spring_概述

Spring 官网Spring Framework&#xff08;Spring&#xff09;文档位置重点内容Overview 官网 Spring官网 Spring Framework&#xff08;Spring&#xff09; 文档位置 重点 IoC容器AOP&#xff1a;面向切面编程AOT&#xff1a;ahead of time&#xff0c;提前编译Web 框架&…