当前位置: 首页 > news >正文

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的两个常用方法,看了其关键代码的实现,也知道了其内部维护着一个缓存。通过分析其源码实现,也解答了开篇抛出的两个问题。

相关文章:

Java源码分析(一)Integer

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

WebRTC音视频通话-WebRTC视频自定义RTCVideoCapturer相机

WebRTC音视频通话-WebRTC视频自定义RTCVideoCapturer相机 在之前已经实现了WebRTC调用ossrs服务&#xff0c;实现直播视频通话功能。但是在使用过程中&#xff0c;RTCCameraVideoCapturer类提供的方法不能修改及调节相机的灯光等设置&#xff0c;那就需要自定义RTCVideoCaptur…...

【基于鲲鹏及openEuler20.03TLS下MySQL8.0.17性能调优】

【基于鲲鹏及openEuler20.03TLS下MySQL8.0.17性能调优】 一、环境说明二、实验过程三、实验小结 一、环境说明 华为云ECS 规格&#xff1a;8vCPU 32G arm架构操作系统&#xff1a;openEuler 20.03.TLSMySQL版本&#xff1a;8.0.17 二、实验过程 创建用户及用户组&#xff1a;…...

GRPC 学习记录

GRPC 安装 安装 grpcio、grpcio-tools、protobuf、 pip install grpcio -i https://pypi.tuna.tsinghua.edu.cn/simple pip install grpcio-tools -i https://pypi.tuna.tsinghua.edu.cn/simple pip install protobuf -i https://pypi.tuna.tsinghua.edu.cn/simple常用类型 p…...

C++语言的QT写软件界面,结合python深度学习模型的综合应用处理方案

C与python问题合集&#xff1a; 后面内容涉及到api的创建问题 如果我用C语言的QT写软件界面&#xff0c;然后用python语言去写和人工智能相关的东西。就比如说一些模型&#xff0c;那么现在我想将用python写的模型放在QT写的软件当中调用&#xff0c;那么请问是否会导致C语言…...

Linux环境下python连接Oracle教程

下载Oracle client需要的 安装包 rpm包下载地址&#xff1a;Oracle官方下载地址 选择系统版本 选择Oracle版本 下载3个rpm安装包 oracle-instantclient12.2-basic-12.2.0.1.0-1.i386.rpm oracle-instantclient12.2-devel-12.2.0.1.0-1.i386.rpm oracle-instantclient12.2-sq…...

第 7 章 排序算法(1)

7.1排序算法的介绍 排序也称排序算法(Sort Algorithm)&#xff0c;排序是将一组数据&#xff0c;依指定的顺序进行排列的过程。 7.2排序的分类&#xff1a; 内部排序: 指将需要处理的所有数据都加载到**内部存储器(内存)**中进行排序。外部排序法&#xff1a; 数据量过大&am…...

wsl,字体乱码问题

配置wsl&#xff0c;字体乱码问题 一、前言 用zsh配置好wsl&#xff0c;每次打开还是会出现乱码&#xff0c;只有再新打开一个终端才会显示字体 如下图&#xff1a;第一次打开&#xff0c;出现乱码 如图&#xff1a;按加号&#xff0c;再开一个新终端才会显示字体。 二、解…...

【NetCore】10-路由定义

文章目录 路由与终结点&#xff1a;如何规划好Web Api1. 路由1.1 路由映射1.2 路由注册方式1.3 路由约束总结: Web Api定义 路由与终结点&#xff1a;如何规划好Web Api 1. 路由 1.1 路由映射 路由系统核心作用是指URL和应用程序Controller的对应关系的一种映射 这种映射的作…...

软考:中级软件设计师:数据库模式、ER模型

软考&#xff1a;中级软件设计师:数据库模式、ER模型 提示&#xff1a;系列被面试官问的问题&#xff0c;我自己当时不会&#xff0c;所以下来自己复盘一下&#xff0c;认真学习和总结&#xff0c;以应对未来更多的可能性 关于互联网大厂的笔试面试&#xff0c;都是需要细心准…...

海量数据迁移,亚马逊云科技云数据库服务为大库治理提供新思路

1.背景 目前&#xff0c;文档型数据库由于灵活的schema和接近关系型数据库的访问特点&#xff0c;被广泛应用&#xff0c;尤其是游戏、互联网金融等行业的客户使用MongoDB构建了大量应用程序&#xff0c;比如游戏客户用来处理玩家的属性信息&#xff1b;又如股票APP用来存储与时…...

DevOps系列文章之 GitlabCICD自动化部署SpringBoot项目

一、概述 本文主要记录如何通过Gitlab CI/CD自动部署SpringBoot项目jar包。 二、前期准备 准备三台 CentOS7服务器&#xff0c;分别部署以下服务&#xff1a; 序号系统IP服务1CentOS7192.168.56.10Gitlab2CentOS7192.168.56.11Runner &#xff08;安装Docker&#xff09;3Cen…...

汽车租赁管理系统/汽车租赁网站的设计与实现

摘 要 租赁汽车走进社区&#xff0c;走进生活&#xff0c;成为当今生活中不可缺少的一部分。随着汽车租赁业的发展&#xff0c;加强管理和规范管理司促进汽车租赁业健康发展的重要推动力。汽车租赁业为道路运输车辆一种新的融资服务形式、广大人民群众一种新的出行消费方式和…...

语句覆盖、条件覆盖、判定覆盖、条件-判定覆盖、路径覆盖

白盒测试是结构测试&#xff0c;主要对代码的逻辑进行验证。 逻辑覆盖率&#xff1a;语句覆盖<条件覆盖<判定覆盖<条件-判定覆盖<组合覆盖<路径覆盖 例子 一、语句覆盖 最基础的覆盖&#xff0c;只要每一个执行处理框内的语句都能执行就可&#xff0c;不用关注…...

二进制逻辑运算符

运算的优先级&#xff1a;非>与>或 1.逻辑与&#xff1a;“ ∧ \wedge ∧“&#xff0c;“ ⋅ \cdot ⋅“&#xff0c;and 在逻辑问题中与是所有的都是真结果才是真&#xff0c;比如&#xff1a; 1010101011 1010101011 1010101011和 1010110010 1010110010 1010110010…...

Bug日记-webstorm运行yarn 命令报错

在windows中输入yarn -v正确输出&#xff0c;在webstrom终端中运行yarn命令输出错误 问题&#xff1a;可能是由于 WebStorm 配置问题导致的。 解决方案&#xff1a; 检查 WebStorm 的终端配置&#xff1a;在 WebStorm 中&#xff0c;点击菜单栏的 “File”&#xff08;文件&am…...

C++11并发与多线程笔记(9) async、future、packaged_task、promise

C11并发与多线程笔记&#xff08;9&#xff09; async、future、packaged_task、promise 1、std::async、std::future创建后台任务并返回值2、std::packaged_task&#xff1a;打包任务&#xff0c;把任务包装起来3、std::promise3、小结 1、std::async、std::future创建后台任务…...

Mr. Cappuccino的第63杯咖啡——Spring之AnnotationConfigApplicationContext源码分析

Spring之AnnotationConfigApplicationContext源码分析 源码分析 源码分析 以上一篇文章《Spring之Bean的生命周期》的代码进行源码分析 AnnotationConfigApplicationContext applicationContext new AnnotationConfigApplicationContext(SpringConfig02.class); LifeCycleBe…...

opencv直方图与模板匹配

import cv2 #opencv读取的格式是BGR import numpy as np import matplotlib.pyplot as plt#Matplotlib是RGB %matplotlib inline def cv_show(img,name):cv2.imshow(name,img)cv2.waitKey()cv2.destroyAllWindows() 直方图 cv2.calcHist(images,channels,mask,histSize,ran…...

Apache Doris 入门教程31:计算节点

需求场景​ 目前Doris是一个典型Share-Nothing的架构, 通过绑定数据和计算资源在同一个节点获得非常好的性能表现. 但随着Doris计算引擎性能持续提高, 越来越多的用户也开始选择使用Doris直接查询数据湖数据. 这类场景是一种Share-Disk场景, 数据往往存储在远端的HDFS/S3上, 计…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)

前言&#xff1a; 最近在做行为检测相关的模型&#xff0c;用的是时空图卷积网络&#xff08;STGCN&#xff09;&#xff0c;但原有kinetic-400数据集数据质量较低&#xff0c;需要进行细粒度的标注&#xff0c;同时粗略搜了下已有开源工具基本都集中于图像分割这块&#xff0c…...

Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换

目录 关键点 技术实现1 技术实现2 摘要&#xff1a; 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式&#xff08;自动驾驶、人工驾驶、远程驾驶、主动安全&#xff09;&#xff0c;并通过实时消息推送更新车…...

【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?

FTP&#xff08;File Transfer Protocol&#xff09;本身是一个基于 TCP 的协议&#xff0c;理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况&#xff0c;主要原因包括&#xff1a; ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...

PH热榜 | 2025-06-08

1. Thiings 标语&#xff1a;一套超过1900个免费AI生成的3D图标集合 介绍&#xff1a;Thiings是一个不断扩展的免费AI生成3D图标库&#xff0c;目前已有超过1900个图标。你可以按照主题浏览&#xff0c;生成自己的图标&#xff0c;或者下载整个图标集。所有图标都可以在个人或…...

rm视觉学习1-自瞄部分

首先先感谢中南大学的开源&#xff0c;提供了很全面的思路&#xff0c;减少了很多基础性的开发研究 我看的阅读的是中南大学FYT战队开源视觉代码 链接&#xff1a;https://github.com/CSU-FYT-Vision/FYT2024_vision.git 1.框架&#xff1a; 代码框架结构&#xff1a;readme有…...

高效的后台管理系统——可进行二次开发

随着互联网技术的迅猛发展&#xff0c;企业的数字化管理变得愈加重要。后台管理系统作为数据存储与业务管理的核心&#xff0c;成为了现代企业不可或缺的一部分。今天我们要介绍的是一款名为 若依后台管理框架 的系统&#xff0c;它不仅支持跨平台应用&#xff0c;还能提供丰富…...

SQL进阶之旅 Day 22:批处理与游标优化

【SQL进阶之旅 Day 22】批处理与游标优化 文章简述&#xff08;300字左右&#xff09; 在数据库开发中&#xff0c;面对大量数据的处理任务时&#xff0c;单条SQL语句往往无法满足性能需求。本篇文章聚焦“批处理与游标优化”&#xff0c;深入探讨如何通过批量操作和游标技术提…...