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源码解析 的相关文章

  • 整数最小值和最大值

    我是编程新手 我正在学习一本Java对象编程书籍 并在计算机上同时执行书中的教程和示例 书中说整数的最大值和最小值是 Integer MAX VALUE 2147483647 Integer MIN VALUE 2147483648 那么好
  • 如何在 C# 中声明大整数

    下面的代码 C 中 是我尝试转换为 C 的代码 DWORD Func X 4 DWORD arg1 DWORD arg2 DWORD arg3 LARGE INTEGER result 1 0 LARGE INTEGER temp1 0 L
  • 在 Ruby 中模拟 int64 溢出

    我是一名资深程序员 但对 Ruby 还很陌生 我正在尝试移植一种名为 CheckRevision 的算法 用于在登录 Battle net 的在线游戏服务之前检查游戏文件的完整性 该算法使用给定的公式对文件进行 哈希 没有无聊的细节 而是不
  • mysql中auto_increment(整数)的限制是多少

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

    我尝试创建一个 javascript 函数validate integer values从文本框 验证它的最佳方法是什么 以便仅integer and float值可以接受吗 数字验证所需的 javascript 函数 remove whi
  • 仅使用整数求平方根

    最近 我在某人的编程课上遇到了一个问题 它要求他们仅使用整数来计算平方根 他们用一个整数来表示小数点之前的部分 用另一个整数来表示小数点之后的部分 问题说不允许使用浮点数 然而 经过一段时间的思考 我似乎无法想出一种不使用浮点的方法 我用谷
  • C 整数溢出

    我正在使用 C 中的整数 试图探索更多关于何时以及如何发生溢出的信息 我注意到 当我添加两个正数时 其总和会溢出 我总是得到一个负数 另一方面 如果我添加两个负数 其总和溢出 我总是得到一个正数 包括 0 我做了一些实验 但我想知道这是否适
  • 如何生成满足某些限制的整数?

    任何人都可以帮我提供生成满足某些限制的整数的技术吗 例如 假设我需要生成整数 x 和 y 使得 100 gt x and y lt x 5 我指的并不是这个特定的示例 而是一些生成满足某些条件的整数的通用技术 嗯 这并不难 选择一个整数 可
  • 如何对无法存储在一个变量中的大数字进行运算

    在Java中 我希望能够对非常大的整数 不能存储在long中 进行操作 我该怎么做 在表现良好的情况下 处理这个问题的最佳方法是什么 我应该创建自己的包含多个长变量的数据类型吗 Example public class MyBigInteg
  • 将两个 Int 值相除以获得 Float 的正确方法是什么?

    我想分两份IntHaskell 中的值并获得结果Float 我尝试这样做 foo Int gt Int gt Float foo a b fromRational a b 但 GHC 版本 6 12 1 告诉我 无法将预期类型 Intege
  • 将 2 个字节转换为整数

    我收到一个 2 个字节的端口号 最低有效字节在前 我想将其转换为整数 以便我可以使用它 我做了这个 char buf 2 Where the received bytes are char port 2 port 0 buf 1 port
  • C++从文件中读取整数并保存到数组中

    我正在制作一个仅从文本文件读取整数的程序 我想创建一个读取整数并将它们存储在数组中的函数 以便稍后可以使用该数组通过冒泡排序对它们进行排序 这是我到目前为止所得到的 但我得到的输出是一些随机的 803234 数字 void read int
  • Java:不使用 Arrays.sort() 对整数数组进行排序

    这是我们 Java 课程的练习之一中的说明 首先 我想说我 做了我的功课 我不仅仅是懒惰地请 Stack Overflow 上的人帮我回答这个问题 在所有其他练习中 这个特定项目一直是我的问题 因为我一直在努力寻找 完美的算法 编写JAVA
  • 反转 Python 整数的位

    给定一个十进制整数 例如 65 如何反转 Python 中的底层位 即以下操作 65 01000001 10000010 130 看来这个任务可以分为三步 将十进制整数转换为二进制表示形式 反转位 转换回十进制 第 2 步和第 3 步看起来
  • Excel VBA 通过简单除法引发溢出错误

    Excel 2013 VBA 这段代码 Sub test On Error GoTo Err Dim p As Double p 362 100 2005 Exit Sub Err If Err Description lt gt And
  • 如何打印前面有一定数量空格的整数?

    C has printf Xd Y 它只打印整数 X 并使其在控制台窗口上占据 Y 空格 例如 printf 3d 10 console 10 printf 5d 5 console 5 我如何在 python 3 中使用它 This pr
  • C++ 编码整数除法

    我的代码运行了 但对于经销商来说 我需要 80 作为总成本的数字 并将其中的 80 取出 我使用 80 100 并得到收集的总成本乘以该数字 但它显示 0 include
  • Arduino 上的串行消息到整数

    我希望我的 Arduino 通过串行通信接收一个整数 你能帮我解决这个问题吗 它应该是这样的形式 int value strtoint Serial read 有多种方法可以读取整数Serial 很大程度上取决于数据发送时的编码方式 Ser
  • 如何仅将数字形式的字符串哈希值转换为整数

    我有从几个不同的 XML 数据库转储导入的哈希行 如下所示 但具有不同的键 Id gt 1 Name gt Cat Description gt Feline Count gt 123 我尝试使用 to i但它将非数字字符串转换为0 Fel
  • 在 R 中使用整数值代替数值(例如 1L 与 1)作为常量的好处

    在 R 源代码中 大多数 但不是全部 函数使用整数值作为常量 colnames lt function x do NULL TRUE prefix col if is data frame x do NULL return names x

随机推荐

  • 基于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