Java源码分析(一)Integer

    当你掌握Java语言到了一定的阶段,或者说已经对Java的常用类和API都使用的行云流水。你会不会有一些思考?比如,这个类是如何设计的?这个方法是怎么实现的?接下来的一系列文章,我们一起学习下Java的一些常见类的源码。本篇,一起分析下Integer的源码。

目录

一、两道Integer的题目

二、Integer类图

三、String转int    

1、Integer.parseInt

2、Integer.valueOf

四、总结 


一、两道Integer的题目

    可能有些同学java水平比较高,或者认为自己没必要去看Integer源码。那你不妨看下接下来这几道题目,看看你是否都能答对。   

1、如下代码输出什么?

public class IntegerTest1 {public static void main(String[] args) {Integer i1 = 100;Integer i2 = 100;Integer i3 = 200;Integer i4 = 200;System.out.println(i1 == i2);System.out.println(i3 == i4);}
}

答案是:true   false

 2、如下代码输出什么?

public class IntegerTest {public static void main(String[] args) {String s = "10";System.out.println(Integer.getInteger(s));}
}

答案是:null(咦,为什么不是10?)

    如果这两道题目都答对了,那你可以叉掉这篇文章,因为我也不想浪费你的时间。如果你答错了,那么不妨一起学习下Integer的源码?

二、Integer类图

    那么,接下来,我们一起看下Integer的源码吧。Integer源码不算短,1800+行代码。其中有很多api是不常用的,因此,我们也仅去挑一些常用的api去看下其实现。如下是Integer及其关联类/接口的类图:

    通过Integer类的类图,我们总结下它的特点:

  • Integer类继承自抽象类Number
  • Integer类实现了Comparable接口
  • Integer类使用final修饰,因此不可以有子类(不能被继承)

三、String转int    

    在日常工作中,我们经常会将一个代表数字的String,转为int,那么Java给我们提供了两个方法:

1、Integer.parseInt

    public static int parseInt(String s) throws NumberFormatException {return parseInt(s,10);}

     在使用这个方法的时候,我们需要注意trycatch一下NumberFormatException,否则当输入的String不是数字或者超过integer的范围时会产生异常。

    另外,该方法默认是10进制,当然我们也可以调用两个参数的方法传入进制去转为其他进制的int,但这不常用:

public static int parseInt(String s, int radix)throws NumberFormatException{...}

    接下来,详细看下该方法的实现:

    首先,会判断传入的String不为null,检验传入的进制参数在范围内[2 , 36],而且会判断字符串的长度大于0,否则会抛出NumberFormatException:

        if (s == null) {throw new NumberFormatException("null");}if (radix < Character.MIN_RADIX) {throw new NumberFormatException("radix " + radix +" less than Character.MIN_RADIX");}if (radix > Character.MAX_RADIX) {throw new NumberFormatException("radix " + radix +" greater than Character.MAX_RADIX");}if (len > 0) {...} else {throw NumberFormatException.forInputString(s);}

      当字符串满足转化为int的条件时,就执行将String转为int的代码(上述被...省略的代码)。我们也分两步来看:

    首先,根据字符串的首字符判断是正数、负数或是非法。

            char firstChar = s.charAt(0);if (firstChar < '0') { // Possible leading "+" or "-"if (firstChar == '-') {negative = true;limit = Integer.MIN_VALUE;} else if (firstChar != '+') {throw NumberFormatException.forInputString(s);}if (len == 1) { // Cannot have lone "+" or "-"throw NumberFormatException.forInputString(s);}i++;}

(1)如果第一个字符是'-',会把表示正负数的negative置为true,同时把其limit置为Integer的最小值;

(2)如果不是'-'且如果不是'+',那说明是其他的字符,抛出异常;

(3)如果首字符是'+'或'-',但是长度为1,说明是"+"或"-",也是非数字,抛出异常。

(4)如果首字符合法,那么i++,接下来看非符号的字符。

    当然,如果首字符不是符号,而是数字,那么就直接走接下来的代码:

            int multmin = limit / radix;int result = 0;while (i < len) {// Accumulating negatively avoids surprises near MAX_VALUEint digit = Character.digit(s.charAt(i++), radix);if (digit < 0 || result < multmin) {throw NumberFormatException.forInputString(s);}result *= radix;if (result < limit + digit) {throw NumberFormatException.forInputString(s);}result -= digit;}return negative ? result : -result;

(1)遍历字符串的字符,调用digit函数,该函数在不能转为数字时返回-1

(2)如果有字符不是数字(digit<0),那么抛出异常。

(3)如果没问题,那就一步步计算转为int,会判断是否超过范围,超过范围则抛出异常

(4)最后,如果是负数返回result,如果是正数,返回-result

    在这里,可能有的同学没看懂,为什么负数返回的是result,而正数返回的是-result。我们把字符串数字转为十进制的方法,比如把"1234"转为十进制,其实是这么来的:

((((1 ✖️10)+ 2)✖️10) + 3)✖️10 + 4

= ((12 ✖️10) + 3) ✖️10 + 4

= (120 + 3)✖️10 + 4

=  123✖️10 + 4

=  1230 + 4

=  1234

    而方法里面其实是反过来实现的:

((((-1 ✖️10)- 2)✖️10) - 3)✖️10 - 4

= ((-12 ✖️10) - 3) ✖️10 - 4

= (-120 - 3)✖️10 - 4

=  -123✖️10 - 4

=  -1230 - 4

=  -1234

    所以,它用的不是正向累加法,而是负向累加法。其实代码里面也有注释(负向累加避免在最大值附近发生意外):

// Accumulating negatively avoids surprises near MAX_VALUE

2、Integer.valueOf

    第二种方法就是Integer.valueOf,该方法最后还是调用的parseInt。注意其返回值是Integer,而不是int。不过,现在已经不用unboxing了,可以直接使用int去接收返回值。

    public static Integer valueOf(String s, int radix) throws NumberFormatException {return Integer.valueOf(parseInt(s,radix));}

    接下来,看看valueOf的实现:

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

    suprise来了,Integer.valueOf( int i)这个方法,出现了IntegerCache这个内部类,而且会返回cache里的对象或者一个新的Integer对象。那么,IntegerCache是什么?

    private static class IntegerCache {static final int low = -128;static final int high;static final Integer[] cache;static Integer[] archivedCache;private IntegerCache() {}static {int h = 127;String integerCacheHighPropValue = VM.getSavedProperty("java.lang.Integer.IntegerCache.high");int size;if (integerCacheHighPropValue != null) {try {size = Integer.parseInt(integerCacheHighPropValue);size = Math.max(size, 127);h = Math.min(size, 2147483518);} catch (NumberFormatException var6) {}}high = h;VM.initializeFromArchive(Integer.IntegerCache.class);size = high - -128 + 1;if (archivedCache == null || size > archivedCache.length) {Integer[] c = new Integer[size];int j = -128;for(int k = 0; k < c.length; ++k) {c[k] = new Integer(j++);}archivedCache = c;}cache = archivedCache;assert high >= 127;}}

    可以看出,Integer内部维护了一个IntegerCache,范围是[-128,127]。valueOf方法,如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。

    这其实解答了我们的第一个问题。 在这里顺便也看下我们的第二个问题,为什么Integer.getInteger("10")返回的是null,而不是10。其实调用的是System.getProperty,跟String转int半毛钱关系没有:

    public static Integer getInteger(String nm, Integer val) {String v = null;try {v = System.getProperty(nm);} catch (IllegalArgumentException | NullPointerException e) {}if (v != null) {try {return Integer.decode(v);} catch (NumberFormatException e) {}}return val;}

四、总结 

    其实Integer我们常用的无非就是这两个String转int的方法,Integer还提供了一些简单的计算方法例如max,min,sum,其实我们也用不到。还有intValue方法,从java1.6开始,我们也不需要拆箱(unboxing)了,所以也用不到。

    本篇基于Integer的两个常用方法,看了其关键代码的实现,也知道了其内部维护着一个缓存。通过分析其源码实现,也解答了开篇抛出的两个问题。

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

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

相关文章

【河源源城紫金】IBM 3650 M4服务器主板维修

河源市源城区某财政单位2台IBM System x3650 M4 服务器黄灯故障无法开机&#xff0c;面板报错BOARD黄灯警告&#xff0c;如上图所示&#xff0c;这位客户通过单位朋友介绍&#xff0c;报修2台单位的IBM服务器&#xff0c;冠峰工程师接到客户报修信息后&#xff0c;售后小哥随即…

Linux笔试题(4)

67、在局域网络内的某台主机用ping命令测试网络连接时发现网络内部的主机都可以连同,而不能与公网连通,问题可能是__C_ A.主机ip设置有误 B.没有设置连接局域网的网关 C.局域网的网关或主机的网关设置有误 D.局域网DNS服务器设置有误 解析&#xff1a;在局域网络内的某台主…

WebGL和OpenGL之间的差异

推荐&#xff1a;使用 NSDT场景编辑器助你快速搭建可二次编辑的3D应用场景 WebGL和OpenGL是与图形处理有关的技术标准&#xff0c;它们在计算机图形中扮演着重要的角色。本文将介绍WebGL和OpenGL的区别&#xff0c;并重点介绍"WebGL"和"OpenGL"的特点。 一…

226、仿真-基于51单片机楼道教室走道智能灯光光照人体感应检测控制Proteus仿真设计(程序+Proteus仿真+配套资料等)

毕设帮助、开题指导、技术解答(有偿)见文未 目录 一、硬件设计 二、设计功能 三、Proteus仿真图 四、程序源码 资料包括&#xff1a; 需要完整的资料可以点击下面的名片加下我&#xff0c;找我要资源压缩包的百度网盘下载地址及提取码。 方案选择 单片机的选择 方案一&…

16.3.2 【Linux】程序的管理

程序之间是可以互相控制的。举例来说&#xff0c;你可以关闭、重新启动服务器软件&#xff0c;服务器软件本身是个程序&#xff0c; 你既然可以让她关闭或启动&#xff0c;当然就是可以控制该程序。 使用kill-l或者是man 7 signal可以查询到有多少个signal。主要的讯号代号与名…

当众讲话与演讲口才沙龙活动策划方案

活动名称&#xff1a;当众讲话与演讲口才沙龙 活动目的&#xff1a; 当众讲话与演讲口才沙龙旨在提升参与者的演讲口才能力&#xff0c;培养自信心和表达能力&#xff0c;促进交流与分享。通过举办此活动&#xff0c;我们希望能够帮助参与者克服公众演讲的恐惧&#xff0c;提…

C++ string 的用法

目录 string类string类接口函数及基本用法构造函数&#xff0c;析构函数及赋值重载函数元素访问相关函数operator[]atback和front 迭代器iterator容量操作size()和length()capacity()max_sizeclearemptyreserveresizeshrink_to_fit string类对象修改操作operatorpush_backappen…

【Flink】Flink窗口触发器

数据进入到窗口的时候,窗口是否触发后续的计算由窗口触发器决定,每种类型的窗口都有对应的窗口触发机制。WindowAssigner 默认的 Trigger通常可解决大多数的情况。我们通常使用方式如下,调用trigger()方法把我们想执行触发器传递进去: SingleOutputStreamOperator<Produ…

vue3.0 element-plus 不同版本 el-popover 循环优化

表格内循环el-popover 渲染以后的页面&#xff0c;数据量很大的时候页面会卡&#xff0c;生成的代码&#xff1a; 解决思路&#xff1a;将el-popover提出来&#xff0c;不参与循环&#xff0c;让el-popover只渲染一次 1、以1.1.0-beta.24版为例&#xff08;低版本&#xff09;…

Bigemap Pro国产基础软件介绍——一款多源数据处理软件

一、软件简介 Bigemap Pro是由成都比格图数据处理有限公司(下称”BIGEMAP”)开发和发行的国产大数据处理基础软件。Bigemap Pro是在BIGEMAP GIS Office基础上&#xff0c;经过十年的用户积累与反馈和技术更新迭代出的新一代基础软件产品。Bigemap Pro国产基础软件集成了数据采…

Qt应用开发(基础篇)——高级纯文本窗口 QPlainTextEdit

一、前言 QPlainTextEdit类继承于QAbstractScrollArea&#xff0c;QAbstractScrollArea继承于QFrame&#xff0c;是Qt用来显示和编辑纯文本的窗口。 滚屏区域基类https://blog.csdn.net/u014491932/article/details/132245486?spm1001.2014.3001.5501框架类QFramehttps://blo…

Python入门【内存管理机制、Python缓存机制、垃圾回收机制、分代回收机制】(三十二)

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱敲代码的小王&#xff0c;CSDN博客博主,Python小白 &#x1f4d5;系列专栏&#xff1a;python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发 &#x1f4e7;如果文章知识点有错误…

回归预测 | MATLAB实现GWO-SVM灰狼优化算法优化支持向量机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现GWO-SVM灰狼优化算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现GWO-SVM灰狼优化算法优化支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09;效果一览基…

基于Matlab 代码实现UWB信号的产生和调制、接收和检测系统

文末提供完整的matlab代码实现下载链接 介绍 本文将分为两部分介绍。在第一部分中,使用 TR 的建模UWB 信号发生器,生成编码二进制数据的脉冲调制信号。这第二部分涉及对接收第一部分中生成的信号的接收器进行建模提取并显示信息。每个信号的时间图和频率响应绘制了阶段。使用MA…

0101前期准备-大数据学习

文章目录 1 前言2 配置VMware虚拟机2.1 设置主机名和固定IP2.2 本地系统与Linux系统配置主机名映射2.3 配置虚拟机之间用户的SSH免密互通2.4 安装JDK环境2.5 关闭防火墙和SELinux2.6 更新时区和同步时间2.7 保存虚拟机快照 结语 1 前言 我们从基础的hadoop开始学起&#xff0c;…

408反向改考自命题的211学校,计算机招生近500人!今年能捡到漏吗?

贵州大学(C) 考研难度&#xff08;☆☆☆&#xff09; 内容&#xff1a;23考情概况&#xff08;拟录取和复试分析&#xff09;、院校概况、23专业目录、23复试详情、各专业考情分析。 正文1498字&#xff0c;预计阅读&#xff1a;3分钟。 2023考情概况 贵州大学计算机相关各…

springBoot 配置文件 spring.resources.add-mappings 参数的作用

在Spring Boot应用中&#xff0c;spring.resources.add-mappings参数用于控制是否将特定路径的资源文件添加到URL路径映射中。 默认情况下&#xff0c;该参数的值为true&#xff0c;即会自动将静态资源&#xff08;例如CSS、JavaScript、图片等&#xff09;的URL路径添加到Spr…

光栅化之扫描填充三角形

重心坐标计算 重心坐标比较简单&#xff0c;取最大包围合再计算点是否在三角形内就行&#xff0c;再根据重心坐标返回的alpha,beta,gamma三个权重值计算 uv映射和depth深度缓冲值&#xff0c;因为是求的重心坐标&#xff0c;感觉效果比插值的要好一点。 求重心坐标 barycentr…

LeetCode128.最长连续序列

我这个方法有点投机取巧了&#xff0c;题目说时间复杂度最多O(n),而我调用了Arrays.sort(&#xff09;方法&#xff0c;他的时间复杂度是n*log(n)&#xff0c;但是AC了&#xff0c;这样的话这道题还是非常简单的&#xff0c;创建一个Hashmap&#xff0c;以nums数组的元素作为ke…

K8S deployment挂载

挂载到emptyDir 挂载在如下目录&#xff0c;此目录是pod所在的node节点主机的目录&#xff0c;此目录下的data即对应容器里的/usr/share/nginx/html&#xff0c;实现目录挂载&#xff1b;图1红框里的号对应docker 的name中的编号&#xff0c;如下俩个图 apiVersion: apps/v1 k…