Integer源码解析

2023-05-16


这篇博客我来整理下以Integer为例整理下包装类的源码。首先来看一段代码:

public class LinkinPark
{

	public static void main(String[] args)
	{
		Integer a = 1;
		Integer b = 1;
		// 下行代码输出true
		System.out.println(a == b);

		Integer c = 128;
		Integer d = 128;
		// 下行代码输出false
		System.out.println(c == d);
	}

}

上面的结果输出估计大家都很明白,前面的包装类那篇博客中我也已经整理到了, Integer类中使用了享元模式,然后用了一个缓存,用来缓存-128到127的数字

现在我们来从头到尾研究下Integer类的源码。

1),Integer类继承Number类,关于Number类我后面会专门整理,实现了comparable接口

public final class Integer extends Number implements Comparable<Integer>
	{
		/**
		 * 最小值:-2147483648
		 */
		@Native
		public static final int MIN_VALUE = 0x80000000;

		/**
		 * 最大值:2147483647
		 * 不好记住肿么办?2开头的10位数字
		 */
		@Native
		public static final int MAX_VALUE = 0x7fffffff;

		/**
		 * 包装类中的基本类型的值
		 */
		private final int value;

		public Integer(int value)
		{
			this.value = value;
		}

		public Integer(String s) throws NumberFormatException
		{
			this.value = parseInt(s, 10);
		}

		/**
		 * 使用第二个参数指定的基数,将字符串参数解析为有符号的整数。
		 * 
		 * @param s 包含要解析的整数表示形式的 String
		 * @param radix 解析 s 时使用的基数,一般为10,用来转换数字
		 * @return 使用指定基数的字符串参数表示的整数
		 * @throws NumberFormatException
		 */
		public static int parseInt(String s, int radix) throws 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");
			}

			int result = 0;
			boolean negative = false;
			int i = 0, len = s.length();
			int limit = -Integer.MAX_VALUE;
			int multmin;
			int digit;

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

		// 以下提供几个转换值的方法
		public byte byteValue()
		{
			return (byte) value;
		}

		public short shortValue()
		{
			return (short) value;
		}

		public int intValue()
		{
			return value;
		}

		public long longValue()
		{
			return (long) value;
		}

		public float floatValue()
		{
			return (float) value;
		}

		public double doubleValue()
		{
			return (double) value;
		}

		@Override
		public int hashCode()
		{
			return Integer.hashCode(value);
		}

		public boolean equals(Object obj)
		{
			if (obj instanceof Integer)
			{
				return value == ((Integer) obj).intValue();
			}
			return false;
		}

		public static int compare(int x, int y)
		{
			return (x < y) ? -1 : ((x == y) ? 0 : 1);
		}

		public static int sum(int a, int b)
		{
			return a + b;
		}

		public static int max(int a, int b)
		{
			return Math.max(a, b);
		}

		public static int min(int a, int b)
		{
			return Math.min(a, b);
		}

	}
以上代码比较简单,我就不多做赘述啦。这里重点来看下Integer类使用的缓存,源码如下:

public final class Integer extends Number implements Comparable<Integer>
{

	/**
	 * Cache to support the object identity semantics of autoboxing for values between
	 * -128 and 127 (inclusive) as required by JLS.
	 * The cache is initialized on first usage. The size of the cache
	 * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
	 * During VM initialization, java.lang.Integer.IntegerCache.high property
	 * may be set and saved in the private system properties in the
	 * sun.misc.VM class.
	 */

	private static class IntegerCache
	{
		static final int low = -128;
		static final int high;
		static final Integer cache[];

		static
		{
			// high value may be configured by property
			int h = 127;
			String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
			if (integerCacheHighPropValue != null)
			{
				try
				{
					int i = parseInt(integerCacheHighPropValue);
					i = Math.max(i, 127);
					// Maximum array size is Integer.MAX_VALUE
					h = Math.min(i, Integer.MAX_VALUE - (-low) - 1);
				}
				catch (NumberFormatException nfe)
				{
					// If the property cannot be parsed into an int, ignore it.
				}
			}
			high = h;

			cache = new Integer[(high - low) + 1];
			int j = low;
			for (int k = 0; k < cache.length; k++)
				cache[k] = new Integer(j++);

			// range [-128, 127] must be interned (JLS7 5.1.7)
			assert IntegerCache.high >= 127;
		}

		private IntegerCache()
		{
		}
	}

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

}
分析一下上面的代码,在Integer的内部封装一个私有的静态内部类,然后在内部类中定义一个静态cache数组,初始化数组将一定范围的整数放到cache数组中,然后在调valueOf

方法的时候首先判断范围然后从缓存数组中去抓取数据,源码还是比较简单的。


缓存是一种非常优秀的设计模式,在Java,JavaEE平台的很多地方都会通过缓存来提高系统的运行性能。简单的说,如果你需要一台电脑,那么你就去买了一台电脑,但你不可

能一直使用这台电脑,你总会离开这台电脑。在你离开电脑的这段时间内,你如何做?你会不会立即把电脑扔掉?当然不会,你会把电脑放在房间,等下次又需要电脑时直接开机

使用,而不是再去购买一台。假设电脑是内存中的对象,而你的房间是内存,如果房间足够大,则可以把所有的曾经用过的各种东西都缓存起来,但这不可能,房间的空间是有限

制的,因此有些东西你用过一次就扔掉了,你只会把一些购买成本大,需要频繁使用的东西保存下来,类似的,Java也会把一些创建成本大,需要频繁使用的对象缓存起来,从而

提高程序的运行性能


前面贴出的代码中缓存那块其实也可以不使用静态内部类,直接使用一个静态数组就OK的,如下代码我自己模拟了一个LinkinInteger,实现了同样的功能。

public final class LinkinInteger
{
	private final int value;

	public LinkinInteger(int value)
	{
		this.value = value;
	}

	private static final int low = -128;
	private static final int high = 127;

	private static final LinkinInteger[] cache = new LinkinInteger[-(low) + high + 1];

	static
	{
		for (int i = 0; i < cache.length; i++)
		{
			cache[i] = new LinkinInteger(i + low);
		}
	}

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

	public static void main(String[] args)
	{
		// 下面3行代码没有使用缓存,所以输出false
		LinkinInteger a = new LinkinInteger(1);
		LinkinInteger b = new LinkinInteger(1);
		System.out.println(a == b);

		// 下面3行代码使用了缓存,所以输出true
		LinkinInteger c = LinkinInteger.valueOf(1);
		LinkinInteger d = LinkinInteger.valueOf(1);
		System.out.println(c == d);
	}

}


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Integer源码解析 的相关文章

  • 有没有一种简单的方法将布尔值转换为整数?

    我是 Scala 新手 我发现需要将布尔值转换为整数 我知道我可以使用类似的东西if x 1 else 0但我想知道是否有首选方法 或者语言中内置的东西 即toInt 如果你想混合Boolean and Int操作使用一个implicit如
  • Javascript解析int64

    如何将长整数 作为字符串 转换为 Javascript 中的数字格式而不用 javascript 对其进行四舍五入 var ThisInt 9223372036854775808 alert ThisInt r parseFloat Thi
  • 整数包装对象仅在值 127 内共享相同的实例? [复制]

    这个问题在这里已经有答案了 这里它们是同一个实例 Integer integer1 127 Integer integer2 127 System out println integer1 integer2 outputs true 但这里
  • 将浮点数向下舍入到最接近的整数?

    我想获取一个浮点数并将其向下舍入到最接近的整数 然而 如果它不是一个整体 我always想要向下舍入变量 无论它与下一个整数的接近程度如何 有没有办法做到这一点 int x 转换为整数将截断 朝向 0 0 例如math trunc 对于非负
  • mysql中auto_increment(整数)的限制是多少

    我有一个mysql数据库 我在其中使用auto increment integer 你能告诉我它可以增加多少整数吗 我们如何提高auto increment的限制 的极限auto increment column 是列的大小 https d
  • 整数构造变体

    大家好 我遇到了一个有趣的事件 正在寻找解释 在 Java 1 6 中 Integer a new Integer 5 Integer b new Integer 5 System out println a b Integer c 5 I
  • 在 C# 整数运算中,a/b/c 是否始终等于 a/(b*c)?

    设a b和c为非大正整数 对于 C 整数算术 a b c 是否始终等于 a b c 对我来说 在 C 中它看起来像 int a 5126 b 76 c 14 int x1 a b c int x2 a b c 所以我的问题是 x1 x2对于
  • 整数转浮点数

    这段代码的工作原理 posToXY Float gt Float gt Integer posToXY a b do let y a b round y 但这不起作用 posToXY Integer gt Integer gt Intege
  • R中整数类和数字类有什么区别

    我想先说我是一个绝对的编程初学者 所以请原谅这个问题是多么基本 我试图更好地理解 R 中的 原子 类 也许这适用于一般编程中的类 我理解字符 逻辑和复杂数据类之间的区别 但我正在努力寻找数字类和整数类之间的根本区别 假设我有一个简单的向量x
  • 从数组中输入多个数字,每个数字检查是否为整数

    每个人 我希望有人能帮我弄清楚C语言的一些东西 这是我第一次认真地做IT方面的作业 我没有经验 而且我正在电子学习中学习 所以老师的帮助不是很好 我需要用C语言开发控制台应用程序 用户需要输入10个整数 如果插入的数字不是整数 需要输出错误
  • 将数字转换为整数列表[重复]

    这个问题在这里已经有答案了 我该如何写magic下面的函数 gt gt gt num 123 gt gt gt lst magic num gt gt gt gt gt gt print lst type lst 1 2 3
  • 对相当大的整数的大集合的操作的快速实现

    描述 我实现了以下类 LabSetInt64 参见下面的代码 这里的目标是尽可能快地操作大量大整数 最多 10M 的值 我的主要要求集中在 至关重要 尽快获取集合的大小 基数 重要 能够非常快速地迭代一组集合 所以 从下面的实现开始 我还有
  • JavaScript 将 NULL 转换为 0

    我正在使用 jQuery 来获取元素的高度 但如果该元素不存在 以下代码将返回 NULL height menu li active ul height returns integer or null 这是一种跨浏览器安全的方法 可以使用以
  • 如何将字符串转换为带有“tail”的浮点数?

    我在将字符串转换为浮点数时遇到问题 print gettype value id returns string var dump value id returns string 34 7140 length 7 float floatval
  • 四个无符号整数的哈希函数 (C++)

    我现在正在编写一个程序 它生成四个无符号 32 位整数作为某个函数的输出 我想对这四个整数进行哈希处理 这样我就可以将该函数的输出与未来的输出进行比较 不过 我在编写一个像样的哈希函数时遇到了麻烦 当我最初编写这段代码时 我对四个整数分别进
  • Android:转换为位图时,回收器视图的宽度和高度必须> 0

    在 Sqlite 中存储文本和图像 并尝试将这些数据检索到 recyclerview 中 当将图像显示到 recyclerview 中时 它显示错误宽度和高度必须 gt 0 在将图像保存在 sqlite 中时 我将位图转换为字节 数据库助手
  • 我如何使用 cout << myclass

    myclass是我写的一个C 类 当我写的时候 myclass x cout lt lt x 我该如何输出10 or 20 2 就像一个integer or a float value 通常通过重载operator lt lt 对于你的班级
  • Java中有默认的数字类型吗

    如果我写这样的东西 System out println 18 哪种类型有 18 是吗int or byte 或者它还没有类型 它不能是 int 因为这样的东西是正确的 byte b 3 这是不正确的 int i 3 byte bb i e
  • 在 Java 中如何将 String 转换为 int?

    我怎样才能转换String值对int type 1234 1234 String myString 1234 int foo Integer parseInt myString 如果你看一下Java 文档 https docs oracle
  • 整数的 localeCompare

    我正在使用 localCompare 来比较一些字符串 这些字符串是数字 我希望订单是数字 我怎样才能做到这一点 排序功能 requestAmountEl find optgroup each function var this jQuer

随机推荐

  • 基于Python的开源人脸识别库:离线识别率高达99.38%——新开源的用了一下感受一下

    该项目是要构建一款免费 开源 实时 离线的网络 app xff0c 支持组织者使用人脸识别技术或二维码识别所有受邀人员 有了世界上最简单的人脸识别库 xff0c 使用 Python 或命令行 xff0c 即可识别和控制人脸 该库使用 dli
  • 5G智慧医疗十大应用场景,你知道多少?

    来源 xff1a 北京物联网智能技术应用协会 都说5G会改变千行百业 xff0c 其中 xff0c 5G医疗健康就是5G技术在医疗健康行业的一个重要应用领域 随着 5G 正式商用的到来以及与大数据 互联网 43 人工智能 区块链等前沿技术的
  • 全网最详细的排列组合系列算法题整理

    写在前面 LeetCode上面排列组合系列几乎所有题目放在一起整理了一下 面试题 08 07 无重复字符串的排列组合 无重复字符串的排列组合 编写一种方法 xff0c 计算某字符串的所有排列组合 xff0c 字符串每个字符均不相同 示例 输
  • 使用IDEA从git拉取分支

    一 打开IDEA xff0c 进入目录 xff1a File gt New gt Project from Version Control 二 打开git工程 xff0c 进行clone对应的链接 填充对应的链接 三 默认下载的是maste
  • 用了cloudflare后,网站提示Sorry, you have been blocked怎么解决?

    其实cloudflare还是非常智能的 xff0c 但有时候为了安全起见 xff0c 我们在网站后台修改参数的时候会被CF拦截 xff0c 我就遇到了好几次提示Sorry you have been blocked的情况 遇到这种情况后 x
  • 下载网页视频的方法

    随着技术的不断更新 xff0c 现在小视频越来越火 xff0c 有的时候想保存浏览的小视频 xff0c 可不知道如何下载 xff1f 对于一些非专业的视频网站的小视频应该通过浏览器的选项是可以下载和保存的 下面就介绍使用浏览器下载的方法 1
  • tomcat8.0.9的安装

    免安装版的tomcat http download csdn net detail u011731233 7632475 这个解压之后 xff0c 在myeclipse中指定到tomcat目录就可以用了 xff0c 也不用配置环境变量 下载
  • 【多线程/C++】阻塞队列的C++多线程 实现 BlockingQueue

    阻塞队列在存放和获取队列中的数据时需要使用多线程 xff0c 一个线程专门负责向队列中存放元素 xff0c 另一个线程专门从队列中获取元素 也可多开辟跟多的线程进行存取 规范的方法也正是存放和获取队列元素分别在不同的线程中实现 阻塞队列实现
  • Log4J使用详解(整理)

    1 Log4j是什么 Log4j是Apache的一个开源项目 xff0c 通过使用Log4j xff0c 我们可以控制日志信息输送的目的地是控制台 文件 GUI组件 xff0c 甚至是套接口服务器 NT的事件记录器 UNIX Syslog守
  • DelphiXE10.2.3实现线程安全访问数据和对象(四)——实现原子自旋锁的无锁对象池

    无锁对象池与无锁Hash是不同应用场景中使用 xff0c 无锁Hash只是预先创建好Hash表 xff08 当然也可以动态Add xff09 后 xff0c 供调用者通过Key值快速找到保存的数据 xff0c 并读取 xff08 这里就只能
  • init进程详细分析--基于android 10

    init进程详细分析 概述 android设备上电 xff0c 引导程序引导进入boot 通常是uboot xff0c 加载initramfs kernel镜像 xff0c 启动kernel后 xff0c 进入用户态程序 第一个用户空间程序
  • commons-logging的使用

    简介 commons logging是Apache commons类库中的一员 Apache commons类库是一个通用的类库 xff0c 提供了基础的功能 xff0c 比如说commons fileupload xff0c common
  • 年度最理性 AI 分析文章:预测 AI 未来,大部分人陷入了 7 大误区

    来源 xff1a 36氪 概要 xff1a 错误的预测会导致大家对不会发生的事情感到恐惧 为什么在人工智能和机器人的预测上总有人不断犯错呢 xff1f 想着预测未来 xff0c 却一不小心就陷入了yy 近年来图像识别突破 Waymo无人车上
  • slf4j的使用

    OK xff0c 现在我们来使用slf4j 概念 SLF4J xff0c 即简单日志门面 xff08 Simple Logging Facade for Java xff09 xff0c 不是具体的日志解决方案 xff0c 它只服务于各种各
  • Java日志管理最佳实践

    原文出处 xff1a http www ibm com developerworks cn java j lo practicelog 感谢原作者 xff0c 感谢ibm网站 xff0c 里面有好多的精华帖 日志记录是应用程序运行中必不可少
  • MySQL数据类型--浮点数类型和定点数类型

    MySQL中使用浮点数类型和定点数类型来表示小数 浮点数类型包括单精度浮点数 xff08 float型 xff09 和双精度浮点数 xff08 double型 xff09 定点数类型就是decimal型 OK xff0c 现在我们来看看这几
  • MySQL数据类型--日期和时间类型

    MySQL中的多种时间和格式数据类型 日期和时间类型是为了方便在数据库中存储日期和时间而设计的 MySQL中有多种表示日期和时间的数据类型 其中 xff0c year类型表示时间 xff0c date类型表示日期 xff0c time类型表
  • MySQL数据类型--二进制类型

    二进制类型是在数据库中存储二进制数据的数据类型 二进制类型包括binary xff0c varbinary xff0c bit xff0c tinyblob xff0c blob xff0c mediumblob xff0c longblo
  • 单行注释和多行注释

    我们在实际编码中 xff0c 总是需要为程序添加一些注释 什么是注释 xff1f 注释就是一段文字 xff0c 这段文字并不是必须的 xff0c 也不直接参与代码运行 注释用来说明某段代码的作用 xff0c 或者说明某个类的用途 xff0c
  • Integer源码解析

    这篇博客我来整理下以Integer为例整理下包装类的源码 首先来看一段代码 xff1a public class LinkinPark public static void main String args Integer a 61 1 I