包装类, 泛型---java

news2024/11/22 23:17:58

目录

一. 包装类

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

1.2 装箱和拆箱

 二. 泛型

2.1什么是泛型

2.2泛型的引入

 2.3 泛型类语法 

 2.4 泛型类的使用

 2.5 裸类型(Raw Type)(了解)

 2.6 泛型是如何编译的 

2.7 泛型的上界

2.8 泛型方法 


一. 包装类

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

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

包装类在之前我们就使用过, 使我们写代码更加的方便 

1.2 装箱和拆箱

装箱(装包): 把一个基本数据类型转变为包装类型

拆箱(拆包): 把一个包装类型转变为基本数据类型

int i = 10 ;
Integer ii = i ; // 自动装箱
Integer ii = Integer . valueOf ( i ); //显示装箱 ---类名.valueOf 说明该方法时用static修饰的
Integer jj = new Integer(10) ;
int j = jj ; // 自动拆箱
int j = jj . intValue (); //显示拆箱

注:拆箱时, 我们可以将数据拆成我们想要的类型 

Integer jj = new Integer(10);

double d = jj.doubleValue();//拆成double类型

System.out.println(d);

//输出结果

10.0

 下面看一道面试题:

思考 : 为什么上述代码只是将100改成200, 输出的结果却不同呢?   

上述我们唯一做的动作就是装箱, 那么装箱时, 调用的方法是Integer.valueOf(), 按住Ctrl点进去查看valueOf的源码, 我们发现:

 我们传入的参数, 如果在一个low和high之间, 那么就返回一个数组某下标的值, 如果不在这个范围内, 那么就new一个对象, 此时即使传入一样的参数, 返回的值肯定是不同的.  那么我们猜测, 200就不在low和high之间, 而100在low和high之间. 

那么我们点进去low和high的源码, 发现low = -128 , high = 127, 我们的猜测是正确的, 那么cache数组是怎么回事呢?

我们计算一下这个数组:

 二. 泛型

2.1什么是泛型

一般的类和方法,只能使用具体的类型 : 要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的代码,这种刻板的限制对代码的束缚就会很大。
----- 来源《 Java 编程思想》对泛型的介绍。
泛型是在 JDK1.5 引入的新的语法,通俗讲,泛型: 就是适用于许多许多类型 。从代码上讲,就是对类型实现了参数化。

2.2泛型的引入

实现一个类,类中包含一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中某个下标的值.
思路:
1. 我们以前学过的数组,只能存放指定类型的元素,例如: int[] array = new int[10]; String[] strs = new String[10];
2. 所有类的父类,默认为 Object 类。数组是否可以创建为 Object?

代码示例:

问题:
以上代码实现后 发现
1. 任何类型数据都可以存放
2. 1 号下标本身就是字符串,但是确编译报错。getPos返回值是Object, 用String接收, 必须进行强制类型转换
虽然在这种情况下,当前数组任何数据都可以存放,但是,更多情况下,我们还是希望他只能够持有一种数据类型。而不是同时持有这么多类型。所以,泛型的主要目的:就是指定当前的容器,要持有什么类型的对象。让编译 器去做检查。 此时,就需要把类型,作为参数传递。需要什么类型,就传入什么类型。
那么我们对上述代码进行改写:

 ① MyArray<T>  -----  类名后的 <T> 代表占位符,表示当前类是一个泛型类

了解: 【规范】类型形参一般使用一个大写字母表示,常用的名称有:
E 表示 Element
K 表示 Key
V 表示 Value
N 表示 Number
T 表示 Type
S, U, V 等等 - 第二、第三、第四个类型

T[] array = (T[])new Object[10] ----  创建泛型类数组

T[] array = (T[])new Object[10], 并不是一个最好的写法, 最好的写法是:

Object[] array = new Object[10];

不能new泛型类型的数组 
T [] ts = new T [ 5 ]; // 是不对的

MyArray<Integer> myArray = new MyArray<>()  -----   创建泛型类对象, 类型后加入 <Integer> 指定当前类型 后面的<>中的内容可以省略

④  myArray.setVal(2,"bit" -----   代码编译报错,此时因为在③处指定类当前的类型,此时编译器会在存放元素的时候帮助我们进行类型检查。

泛型, 是编译时期的机制, 在运行时, 没有泛型的概念

注:<>中的内容不能是基本数据类型, 只能是引用类型/包装类

想要存放String类型的数据:

 2.3 泛型类语法 

class 泛型类名称 < 类型形参列表 > {
        // 这里可以使用类型参数
}
class ClassName < T1 , T2 , ..., Tn > {
}
class 泛型类名称 < 类型形参列表 > extends 继承类 /* 这里可以使用类型参数 */ {
        // 这里可以使用类型参数
}
class ClassName < T1 , T2 , ..., Tn > extends ParentClass < T1 > {
        // 可以只使用部分类型参数
}

 2.4 泛型类的使用

泛型类 < 类型实参 > 变量名 ; // 定义一个泛型类引用
new 泛型类 < 类型实参 > ( 构造方法实参 ); // 实例化一个泛型类对象
MyArray < Integer > list = new MyArray < Integer > ();
//当编译器可以根据上下文推导出类型实参时,可以省略类型实参的填写
MyArray < Integer > list = new MyArray <> (); // 可以推导出实例化需要的类型实参为 Integer
注意:泛型只能接受类,所有的基本数据类型必须使用包装类!

 2.5 裸类型(Raw Type)(了解)

裸类型是一个泛型类但没有带着类型实参,例如 MyArrayList 就是一个裸类型

MyArray list = new MyArray();  

小结:
1. 泛型是将数据类型参数化,进行传递
2. 使用 <T> 表示当前类是一个泛型类。
3. 泛型目前为止的优点:数据类型参数化,编译时自动进行类型检查和转换

 2.6 泛型是如何编译的 

那么,泛型到底是怎么编译的?这个问题,也是曾经的一个面试问题。泛型本质是一个非常难的语法,要理解好他还是需要一定的时间打磨。
通过命令: javap -c 查看字节码文件,所有的 T 都是 Object
在编译的过程当中,将所有的 T替换为Object 这种机制,我们称为: 擦除机制
Java 的泛型机制是在编译级别实现的。编译器生成的字节码在运行期间并不包含泛型的类型信息。

2.7 泛型的上界

 在定义泛型类时,有时需要对传入的类型变量做一定的约束,可以通过类型边界来约束。

语法:

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

例:

public class MyArray < E extends Number > {
...
}

表示: 只接受 Number 或 Number的子类型 作为 E 的类型实参 

MyArray < Integer > l1 ; // 正常,因为 Integer Number 的子类型
MyArray < String > l2 ; // 编译错误,因为 String 不是 Number 的子类型

了解:

1.  没有指定类型边界 E,可以视为 E extends Object  

2. 泛型没有下界

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

 显然这样是错误的, 因为擦除机制将T替换成Object类, 而引用类型是不能直接比较大小的, 需要使用compareTo方法, 并实现Comparable接口,  我们点进去Object的源码看发现: 

Object类并没有实现Comparable接口 

正确的写法应该是:

意味着, 传入的参数必须是继承了Comparable接口的类, 那么Integer我们点进去查看:

 Integer是继承了Comparable接口的. 

如果我们重新定义一个类当参数:

是不被允许的, 因为没有Person没有实现Comparable接口

正确写法:

2.8 泛型方法 

语法:

方法限定符 < 类型形参列表 > 返回值类型 方法名称 ( 形参列表 ) { ... }

上述代码可以写成 泛型方法:

 

当这个泛型方法是静态的时,  我们就不用实例化对象, 直接通过类来调用泛型方法 

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

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

相关文章

爱智EdgerOS之深入解析AI图像引擎如何实现AI视觉开发

一、前言 AI 视觉是为了让计算机利用摄像机来替代人眼对目标进行识别&#xff0c;跟踪并进一步完成一些更加复杂的图像处理。这一领域的学术研究已经存在了很长时间&#xff0c;但直到 20 世纪 70 年代后期&#xff0c;当计算机的性能提高到足以处理图片这样大规模的数据时&am…

DSP处理器及其体系结构特点(您都用过哪些DSP?)

DSP处理器概述 数字信号处理器&#xff08;Digital Signal Processor&#xff0c;DSP&#xff09;是一种专门设计用于执行数字信号处理任务的微处理器类型。与通用微处理器&#xff08;如CPU&#xff09;相比&#xff0c;DSP处理器在处理数字信号时具有更高的性能和效率。 用途…

JAVA程序如何打jar和war问题解决

背景: 近期研究一个代码审计工具 需要jar包 jar太多了 可以将jar 打成war包 首先看下程序目录结构 pom.xml文件内容 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"ht…

数据库后门是什么?我们要如何预防它的危害

数据库后门是黑客在数据库中安装的一种特殊程序或代码&#xff0c;可以绕过正常的认证和授权机制&#xff0c;从而获取数据库的敏感信息或者控制整个数据库。黑客可以通过各种方式安装后门&#xff0c;比如利用漏洞、钓鱼、社会工程学等。 数据库后门的危害主要体现在以下几个方…

GPTs应用:创新无限,生态扩容

今天分享的GPTs系列深度研究报告&#xff1a;《GPTs应用&#xff1a;创新无限&#xff0c;生态扩容》。 &#xff08;报告出品方&#xff1a;华泰证券&#xff09; 报告共计&#xff1a;20页 GPTs 发展现状&#xff1a;从 AI 工具到开发平台&#xff0c;掀起全民开发浪潮 11…

YOLOv5独家原创改进:SPPF自研创新 | 可变形大核注意力(D-LKA Attention),大卷积核提升不同特征感受野的注意力机制

💡💡💡本文自研创新改进: 可变形大核注意力(D-LKA Attention)高效结合SPPF进行二次创新,大卷积核提升不同特征感受野的注意力机制。 收录 YOLOv5原创自研 https://blog.csdn.net/m0_63774211/category_12511931.html 💡💡💡全网独家首发创新(原创),适合p…

Docker三 | 数据卷

目录 Docker数据卷简介 添加数据卷的命令 容器数据卷的继承 Docker数据卷简介 Docker容器产生的数据&#xff0c;如果不备份&#xff0c;当容器实例删除后&#xff0c;容器中的数据也会消失&#xff0c;为了保存数据可以在Docker中使用数据卷。Docker数据卷是宿主机的一个可以…

【LeetCode】2703. 返回传递的参数的长度

返回传递的参数的长度 题目题解 题目 请你编写一个函数 argumentsLength&#xff0c;返回传递给该函数的参数数量。 示例 1&#xff1a; 输入&#xff1a;args [5] 输出&#xff1a;1 解释&#xff1a; argumentsLength(5); // 1只传递了一个值给函数&#xff0c;因此它应返…

搞懂内存函数

引言 本文介绍memcpy的使用和模拟实现、memmove的使用和模拟实现、memcmp使用、memset使用 ✨ 猪巴戒&#xff1a;个人主页✨ 所属专栏&#xff1a;《C语言进阶》 &#x1f388;跟着猪巴戒&#xff0c;一起学习C语言&#x1f388; 目录 引言 memcpy memcpy的使用 memcpy的…

PyTorch: 基于VGG16处理MNIST数据集的图像分类任务

引言 在本博客中&#xff0c;小编将向大家介绍如何使用VGG16处理MNIST数据集的图像分类任务。MNIST数据集是一个常用的手写数字分类数据集&#xff0c;包含60,000个训练样本和10,000个测试样本。我们将使用Python编程语言和PyTorch深度学习框架来实现这个任务。 在Conda虚拟环…

鸿蒙开发组件之Image

Image组件加载图片方式有三种&#xff1a; 1、网络地址加载 直接Image(xxxx),添加上图片的网络地址就可以了。注意&#xff1a;真机、模拟题调试需要申请"ohos.permission.INTERNET"权限 Image(https://xxxxxxx) 2、PixelMap格式加载像素图 Image(PixelMapObjec…

根据年份和第几周来获取,那一个周的周天日期

在工作中遇到这个问题&#xff0c;仓库有物料录入&#xff0c;告诉了年份和这个年的第几周&#xff0c;要求把时间转换为XXXX-XX-XX的格式。日期为那个周的最后一天&#xff08;周天&#xff09; 在Java中想要获取特定年份和周数的周天日期&#xff0c;可以使用LocalDate类 pu…

【SpringBoot】响应

controller方法中的return的结果&#xff0c;使用ResponseBody注解&#xff08;方法注解或类注解&#xff09;响应给服务器。 RestController Controller ResponseBody 类上有RestController注解或ResponseBody注解时&#xff1a;表示当前类下所有的方法返回值做为响应数据…

四招打造完美分层自动化测试框架,让测试更高效!

写在前面 我们刚开始做自动化测试&#xff0c;可能写的代码都是基于原生写的代码&#xff0c;看起来特别不美观&#xff0c;而且感觉特别生硬。 来看下面一段代码&#xff1a; 具体表现如下&#xff1a; driver对象在测试类中显示 定位元素的value值在测试类中显示 定位元素…

数据表排序

指针用的有点少了&#xff0c;有点不适应 用的冒泡排序 代码如下&#xff1a; #include<stdio.h> int num[100][100]; int * p[100], jud[100]; int judge(int i, int j, int rank); int m, n, k;int main(void) {scanf("%d%d%d", &m, &n, &k);f…

字符串函数strtok

1.调用格式&#xff1a; 2.调用形式&#xff1a;char*strtok(char*p1,const char*p2),其中第二个是由分隔符组成的字符串&#xff0c;第一个为需要分隔的字符串 3.调用目的&#xff1a;将分隔符之间的字符串取出 4.调用时一般将源字符串拷贝后调用&#xff0c;因为此函数会将…

C++11原子操作atomic

文章目录 原子操作atomic原子操作的相关函数原子操作的特点“平凡的”与“合格的” 原子操作atomic 前面我们介绍了互斥锁等一系列多线程相关操作&#xff0c;这里我们来说下原子操作atomic。 可以理解为原子变量就是将上面的操作进行了整合的一个全新变量&#xff0c;但是实际…

sensitive word 敏感词(脏词) 如何忽略无意义的字符?达到更好的过滤效果?

忽略字符 说明 我们的敏感词一般都是比较连续的&#xff0c;比如 傻帽 那就有大聪明发现&#xff0c;可以在中间加一些字符&#xff0c;比如【傻!#$帽】跳过检测&#xff0c;但是骂人等攻击力不减。 那么&#xff0c;如何应对这些类似的场景呢&#xff1f; 我们可以指定特…

带大家做一个,易上手的家常可乐鸡翅

将鸡翅从冰箱中拿出 泡水解冻 这里 我用的二十个 将葱切段 切一些蒜片 有姜也可以切一些小片下来 这里 家里没姜了 六根干辣椒 一把花椒 等鸡翅化开之后 清洗干净 然后 如下图 中间位置切两刀 方便入味 起锅烧油 然后 下鸡翅 干辣椒 花椒 先翻炒一下 这里不需要放水 鸡翅会…

JavaScript基础知识整理(最全知识点, 精简版,0基础版)

文章目录 一、输入和输出内容 1.1 输出 1.1.1 在浏览器的控制台输出打印 1.1.2 直接在浏览器的页面上输出内容 1.1.3 页面弹出警告对话框 1.2 输入 二、变量 2.1 变量是什么 2.2 变量的声明和赋值 2.3 变量的命名规范和规范 三、变量扩展&#xff08;数组&#xff09; 3.1 数组…