java包装类简单认识泛型

1 包装类

Java 中,由于基本类型不是继承自 Object ,为了在泛型代码中可以支持基本类型, Java 给每个基本类型都对应了一个包装 类型。类中比如由属性/方法 使用比较方便

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

1.2 装箱和拆箱

装包/装箱 : 基本数据类型=>包装类类型

拆箱/拆包 : 包装类型=>基本类型 

int i = 10;
// 装箱操作,新建一个 Integer 类型对象,将 i 的值放入对象的某个属性中
Integer ii = Integer.valueOf(i);
Integer ij = new Integer(i);   // 显示装箱 底层还是调用Integer.valueOf(i);// 拆箱操作,将 Integer 对象中的值取出,放到一个基本数据类型中
int j = ii.intValue();  // 显示拆箱

1.3 自动装箱和自动拆箱  

可以看到在使用过程中,装箱和拆箱带来不少的代码量,所以为了减少开发者的负担, java 提供了自动机制
int i = 10;
Integer ii = i; // 自动装箱
Integer ij = (Integer)i; // 自动装箱int j = ii; // 自动拆箱
int k = (int)ii; // 自动拆箱

阿里面试题

下列代码输出什么,为什么?
public static void main(String[] args) {
Integer a = 127;
Integer b = 127;
Integer c = 128;
Integer d = 128;
System.out.println(a == b);
System.out.println(c == d);
}

答案: 

解释: 四行代码都是对应自动装箱操作, 而自动装箱操作底层还是调用Integer.valueOf(i);

cache 是一个提前开辟好的长度为256的数组,

cache[0] 存放的是 -128  (-128 + (- ( -128 ) ) = 0 )

cache[255]存放的是127 (127 + (- ( -128 ) ) = 0 )

也就是说当传入valueOf()的值范围在-128~127之间时, 返回的值都是实现设置好的,因此为true

但128超出范围, 必须new一个新值, 两个值在不同地址上因此只能是false 

2 什么是泛型

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

3 引出泛型

实现一个类,类中包含一个数组成员,使得数组中可以存放 任何类型 的数据,也可以根据成员方法返回数组中某个下标位置上的值?
思路:
  1. 我们以前学过的数组,只能存放指定类型的元素,例如:int[] array = new int[10]; String[] strs = new String[10];
  2. 所有类的父类,默认为Object类。数组是否可以创建为Object?
class MyArray {public Object[] objects = new Object[10];public Object getPos(int pos) {return objects[pos];}public void setVal(int pos,Object val) {objects[pos] = val;}
}
public class TestDemo {public static void main(String[] args) {MyArray myArray = new MyArray();myArray.setVal(0,10);myArray.setVal(1,"hello");//字符串也可以存放String ret = myArray.getPos(1);//编译报错System.out.println(ret);}
}

编译报错地方  必须进行强制类型转化才能输出

String ret = (String)myArray.getPos(1);//编译报错
System.out.println(ret);
问题:以上代码实现后 发现
1. 任何类型数据都可以存放
2. 1 号下标本身就是字符串,但是确编译报错。必须进行强制类型转换
虽然在这种情况下,当前数组任何数据都可以存放,但是,更多情况下,我们还是希望他只能够持有一种数据类型。而不是同时持有这么多类型。所以,泛型的主要目的:就是指定当前的容器,要持有什么类型的对象。让编译 器去做检查。 此时,就需要把类型,作为参数传递。需要什么类型,就传入什么类型。
/*** @param <T>  T是一个占位符,表示当前类是一个泛型类**/
class MyArray2<T> {//public Object[] objects = new Object[10];public T[] objects = (T[])new Object[10];//public T[] objects = new T[10];  //1public T getPos(int pos) {return objects[pos];}public void setVal(int pos,T val) {objects[pos] = val;}
}
public static void main2(String[] args) {MyArray<Integer> myArray1 = new MyArray<Integer>(); //2myArray1.setVal(0,48);myArray1.setVal(1,10);int val = myArray1.getPos(1); //3System.out.println(val);System.out.println("=======");MyArray<String> myArray2 = new MyArray<>();myArray2.setVal(0,"hello");myArray2.setVal(1,"bit");String ret = myArray2.getPos(1);System.out.println(ret);}
1.注释 1 处,不能 new 泛型类型的数组
        意味着: T [] ts = new T [ 5 ]; // 是不对的, 这样写会报错, 报错原因后边说
        因为泛型不能在运行中被识别, 只能在编译中才能被识别
        课件当中的代码:T[] array = (T[])new Object[10]; 是否就足够好,答案是未必的。这块问题一会儿介绍。

2. 注释 2 处,类型后加入 <Integer> 指定当前类型
3. 注释 3 处,不需要进行强制类型转换

泛型存在的意义:

  1. 在编译的时候, 帮我进行类型的检查
  2. 在编译的时候, 帮我进行类型的转换

运行的时候是没有泛型概念的, JVM当中是没有泛型的

4. 泛型是如何编译的 

4.1 擦除机制

那么,泛型到底是怎么编译的?这个问题,也是曾经的一个面试问题。泛型本质是一个非常难的语法,要理解好他 还是需要一定的时间打磨
在编译的过程当中,将所有的 T 替换为 Object 这种机制,我们称为: 擦除机制

Java的泛型机制是在编译级别实现的。编译器生成的字节码在运行期间并不包含泛型的类型信息。  

4.2 提出问题:

4.2.1

为什么,public T[] objects = new T[10]; 是不对的,编译的时候,替换为Object,不是相当于:Object[] ts = new Object[5]吗?那既然会替换为Object为什么会报错呢?

答案: 因为Java数组语法上要求new后边必须跟一个具体类型

4.2.2 为什么T[] array = (T[])new Object[10 不够好

       我们提供一个getArray()方法来 实例化泛型类型数组
当我们运行getArray()方法时候就会报错,哪怕强转都会报错,  因为擦除机制编译时返回的是Object类型,
而Object类型无论如何都不能转为Integer具体类型
返回的 Object 数组里面,可能存放的是任何的数据类型,可能是 String ,可能是 Person ,运行的时
候,直接转给 Integer 类型的数组,编译器认为是不安全的

改进方法1: 用Object类型接收 

既然不允许强转Object  那就只能用Object类型接收 

class MyArray2<T> {//public Object[] objects = new Object[10];public T[] objects = (T[])new Object[10];//public T[] objects = new T[10];  //1public T getPos(int pos) {return objects[pos];}public void setVal(int pos,T val) {objects[pos] = val;}public Object[] getArray() {   // 也可以返回T[] 都一样最后也编译成Object[]return objects;}
}
public static void main2(String[] args) {MyArray<Integer> myArray1 = new MyArray<Integer>(); Object[] integers = myArray1.gerArray();    
}

要是必须用具体Integer类型来接收呢? 更好的

改进方法2: 用反射创建指定类型的数组(了解即可)

改进方法1 myArray1内部创建过程中用是泛型类型数组, 而方法2内部创建过程中直接使用指定类型数组, 当然就不在需要因为擦除机制编译成Object类型了

class MyArray2<T> {//public Object[] objects = new Object[10];public T[] objects;//public T[] objects = new T[10];  //1/*** 通过反射创建,指定类型的数组* @param clazz* @param capacity*/public MyArray(Class<T> clazz, int capacity) {array = (T[])Array.newInstance(clazz, capacity);}public T getPos(int pos) {return objects[pos];}public void setVal(int pos,T val) {objects[pos] = val;}public T[] getArray() {return objects;}
}
public static void main2(String[] args) {MyArray2<Integer> myArray2 = new MyArray2<>(Integer.class,10);Integer[] integers = myArray2.getArray();   
}

最佳方法

那在实际工作中通常只需要直接使用Object类型数组就可以了, 只需要注意一下setVal()时存放T类型就可以了, getPos()取数据时候强制类型转换就可以了, 当然也需要用Object类型数组接收getArray()结果

我们以后就用这个方式写代码 

 

5. 泛型的上界

问题引入 , 红色部分出现的原因?

答案:
<>当中必须存放引用数据类型, 而引用数据类型的数据之间比较大小必须通过 实现 Comparable 接口,并调用其中的compareTo()方法
但是泛型T在编译的时候被擦除成Object类型, 而Object类型并没有实现Comparable接口,因此出现报错
这个  extends Comparable <E > 就是为泛型添加一个上界, 避免被擦除成Object , 而是擦除成实现了 Comparable 接口的类型(即上界)
另外传入的泛型T 必须 实现Comparable 接口的类型(即上界类型)

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

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

相关文章

分布式版本控制工具——git

✅<1>主页&#xff1a;&#xff1a;我的代码爱吃辣 &#x1f4c3;<2>知识讲解&#xff1a;Linux——git ☂️<3>开发环境&#xff1a;Centos7 &#x1f4ac;<4>前言&#xff1a;git是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很…

学习笔记——树上哈希

普通子树哈希 树上的很多东西都是转化成链上问题的&#xff0c;比如树上哈希 树上哈希&#xff0c;主要是用于树的同构这个东西上的 什么是树的同构&#xff1f; 如图&#xff0c;不考虑节点编号&#xff0c;三棵树是同构的 将树转化成链&#xff0c;一般有两种方式&#xf…

JS防抖和节流在前端开发中的应用场景

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 防抖&#xff08;Debouncing&#xff09;⭐ 节流&#xff08;Throttling&#xff09;⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端…

KT142C-sop16语音芯片ic内置320Kbyte_USB更新内置空间详细说明

KT142C内置的是320K的空间&#xff0c;但是实际的大小&#xff0c;在电脑里面显示&#xff0c;应该是315Kbyte。 打开我的电脑&#xff0c;芯片连接PC之后&#xff0c;自动多出来了一个U盘&#xff0c;如下图所示&#xff1a; 这里的空间只有315KB &#xff0c;因为文件系统占…

猫头虎的技术笔记:Spring Boot启动报错解决方案

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

Java项目基于SpringBoot藏区特产销售系统,可作为毕业设计

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W,Csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 今天为大家带来的是基于 Java SpringBootVue 的藏区特产销售系统 文章目录 1. 简介2.主要技术3 功能分析4 系…

【2023高教社杯】B题 多波束测线问题 问题分析、数学模型及参考文献

【2023高教社杯】B题 多波束测线问题 问题分析、数学模型及参考文献 1 题目 1.1 问题背景 多波束测深系统是利用声波在水中的传播特性来测量水体深度的技术&#xff0c;是在单波束测深的基础上发展起来的&#xff0c;该系统在与航迹垂直的平面内一次能发射出数十个乃至上百个…

Redis集群3.2.11离线安装详细版本(使用Ruby)

1.安装软件准备 1.Redis版本下载 Index of /releases/http://download.redis.io/releases/ 1.2gcc环境准备 GCC(GNU Compiler Collection,GNU编译器套件)是一套用于编译程序代码的开源编译器工具集。它的主要用途是将高级编程语言(如C、C++、Fortran等)编写的源代码转换…

SEO百度优化基础知识全解析(了解百度SEO标签作用)

百度SEO优化的作用介绍&#xff1a; 百度SEO优化是指通过对网站的内部结构、外部链接、内容质量、用户体验等方面进行优化&#xff0c;提升网站在百度搜索结果中的排名&#xff0c;从而提高网站的曝光率和流量。通过百度SEO优化&#xff0c;可以让更多的潜在用户找到你的网站&…

软件设计模式(二):工厂、门面、调停者和装饰器模式

前言 在这篇文章中&#xff0c;荔枝将会梳理软件设计模式中的四种&#xff1a;工厂模式、Facade模式、Mediator模式和装饰器Decorator模式。其中比较重要的就是工厂模式和装饰器模式&#xff0c;工厂模式在开发中使用的频数比较高。希望荔枝的这篇文章能讲清楚哈哈哈哈&#xf…

【STM32】文件系统FATFS与Flash的初步使用

文件系统简介 简介可以不看&#xff0c;直接看移植步骤 文件系统是介于应用层和底层间的模糊层。底层提供API&#xff0c;比如说使用SDIO或者SPI等读写一个字节。文件系统把这些API组合包装起来&#xff0c;并且提供一些列函数&#xff0c;我们可以使用这些函数进行更进一步的…

分享一个python基于数据可视化的智慧社区服务平台源码

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人七年开发经验&#xff0c;擅长Java、Python、PHP、.NET、Node.js、微信小程序、爬虫、大数据等&#xff0c;大家有这一块的问题可以一起交流&#xff01; &#x1…

MySQL数据类型

目录 MySQL数据类型 数据类型分类 数值类型 tinyint类型 bit类型 float类型 decimal类型 字符串类型 char类型 varchar类型 char和varchar比较 时间日期类型 enum和set类型 MySQL数据类型 数据类型的作用&#xff1a; 决定了存储数据时应该开辟的空间大小。决定…

CocosCreator3.8研究笔记(十二)CocosCreator 字体资源理解

Cocos Creator 常用的字体资源有三种&#xff1a;系统字体、动态字体、位图字体。 一、系统字体 系统字体是调用运行平台自带的系统字体来渲染文字&#xff0c;不需要用户在项目中添加任何相关资源。 使用系统字体&#xff0c; Label 组件 Use System Font 属性需要勾选。 Fo…

手写签名到背景上合为1张图

手写签名到背景上合为1张图 package.json中 "signature_pad": "3.0.0-beta.3"<template><div class"home"><canvas id"canvas" width"500" height"300"></canvas><button click"…

【计算机基础知识4】网络通信协议:TCP、UDP、WebSockets

目录 一、TCP&#xff08;传输控制协议&#xff09; 1. TCP的特点 2. TCP的连接建立和终止 3. TCP的可靠性机制 4. TCP的流量控制 二、UDP&#xff08;用户数据报协议&#xff09; 1. UDP的特点 2. UDP的使用场景 三、WebSockets 1. WebSockets协议的特点 2. WebSock…

长安链BaaS服务平台调研

目录 一、菜单功能二、其他说明2.1、服务平台的部署方式2.2、链本身2.3、建链流程2.4、支持连接已部署的链2.5、链治理投票2.6、支持动态节点操作2.7、支持应用 长安链ChainMaker管理平台文档地址&#xff1a;https://docs.chainmaker.org.cn 一、菜单功能 菜单子菜单/功能点…

强大的JTAG边界扫描(1):基本原理介绍

文章目录 1. 什么是边界扫描&#xff1f;2. JTAG硬件接口3. 边界扫描相关的软硬件4. 学习资料5. 总结 我是怎么了解到边界扫描的呢&#xff1f; 这就要从我淘到一块FPGA板卡的事情说起了。 前段时间我在某二手平台上淘了一块FPGA板子&#xff0c;它长这样&#xff1a; 板子的…

【广州华锐互动】元宇宙技术如何赋能传统工业企业?

随着科技的飞速发展&#xff0c;我们正处于工业革命4.0的时代&#xff0c;数字化、网络化和智能化正在深刻地改变着我们的生活和工作方式。在这个变革的大潮中&#xff0c;工业元宇宙平台应运而生&#xff0c;为企业带来了前所未有的机遇和挑战。 广州华锐互动开发的工业元宇宙…

vite搭建vue3项目

参考视频 1.使用npm搭建vite项目,会自动搭建vue3项目 npm create vitelatest yarn create vite2.手动搭建vue3项目 创建一个项目名称的文件夹执行命令&#xff1a;npm init -y 快速的创建一个默认的包信息安装vite: npm i vite -D -D开发环境的依赖 安装vue,现在默认是vue3.…