本文主要介绍一些Java中你不知道的关于整数的相关信息。通过示例代码详细介绍,对您的学习或工作有一定的参考价值。有需要的朋友就跟着下面的边肖学习吧。
前言
本文主要介绍Java中整数的相关内容,分享给大家参考。下面不多说了。我们来看看详细的介绍。
实参形参
前几天看到朋友圈分享一篇文章《Java函数的传参机制——你真的了解吗?》。
一些触发器,而且之前学过Java Integer,所以写这篇文章希望对你有帮助。
交换
我们先来看一个例子。
请用Java完成swap函数,交换两个整数类型的值。
公共静态void测试()引发异常{
整数a=1,b=2;
互换(a,b);
System.out.println('a=' a ',b=' b);
}
静态void交换(整数a,整数b){
//需要实现的部分
}
第一次
如果你不知道Java对象如何在内存中分配,方法如何传递参数,你可以写下面的代码。
公共静态void swapOne(整数a,整数b)引发异常{
整数aTempValue=a;
a=b;
b=aTempValue
}
运行结果表明,A和B的值没有交换。
所以我们来看看上面的程序运行时,Java对象是如何在内存中分配的:
目标地址分配
由此可见,两个方法的局部变量表分别保存了对两个对象A和B的实际数据地址的引用。
上面实现的swap函数只交换swap函数中局部变量A和局部变量B的引用,不交换JVM堆中的实际数据。
所以主函数中A和B引用的数据是不交换的,所以主函数中局部变量的A和B不会改变。
那么如何交换主函数中的数据呢?
第二次
按照上面的做法,可以考虑在JVM堆上交换A和B的数据值?
让我们简单看一下对象Integer。其中只有一个对象级的int类型值来表示对象的值。
所以我们用反射来修改值,代码如下:
公共静态void swapTwo(整数a1,整数b1)引发异常{
field value field=integer . class . getdeclaredfield(' value ');
valuefield . set accessible(true);
int tempAValue=value field . getint(a1);
valueField.setInt(a1,B1 . int value());
valueField.setInt(b1,tempAValue);
}
结果在意料之中。
惊喜
以上程序运行后,如果我声明一个整数c=1,d=2;会发生什么?
示例程序如下:
公共静态void swapTwo(整数a1,整数b1)引发异常{
field value field=integer . class . getdeclaredfield(' value ');
valuefield . set accessible(true);
int tempAValue=value field . getint(a1);
valueField.setInt(a1,B1 . int value());
valueField.setInt(b1,tempAValue);
}
公共静态void testThree()引发异常{
整数a=1,b=2;
swapTwo(a,b);
system . out . println(' a=' a ');b=' b ');
整数c=1,d=2;
system . out . println(' c=' c ');d=' d);
}
输出结果如下:
a=2;b=1
c=2;d=1
不奇怪!不奇怪!不刺激!
深入
到底发生了什么?让我们来看看反编译的代码:
作者反编译了这个。通过使用IDE工具直接创建类文件。
公共静态void testThree()引发异常{
integer a=integer . value of(1);
integer b=integer . value of(2);
swapTwo(a,b);
system . out . println(' a=' a ');b=' b ');
integer c=integer . value of(1);
integer d=integer . value of(2);
system . out . println(' c=' c ');d=' d);
}
整数方法。valueof (int)用于Java自动将原始类型int打包成整数类型的过程中。
可以肯定的是,这个方法内部封装了一些操作,使得我们修改Integer.value,具有全局影响。
这部分涉及的代码全部一次粘贴(PS:不拖的作者是个好码农):
公共类整数{
/**
* @从1.5开始
*/
(int i)的公共静态整数值{
if(I=整数缓存。低I=整数缓存。高)
返回整数缓存。cache[I(--整数缓存。低)];
返回新的整数;
}
私有静态类IntegerCache {
静态最终int low=-128;
静态最终(同Internationalorganizations)国际组织高;
静态最终整数缓存[];
静态{
//高值可以由属性配置
int h=127
字符串integerCacheHighPropValue=
星期日杂项虚拟机。getsavedproperty(' Java。郎。整数。整数缓存。高’);
if (integerCacheHighPropValue!=null) {
尝试{
int I=parse int(integerCacheHighPropValue);
i=Math.max(i,127);
//最大数组大小是整数。最大值
h=Math.min(i,整数MAX _ VALUE-(-低)-1);
} catch(NumberFormatException nfe){
//如果该属性无法解析为int,则忽略它。
}
}
高=h;
缓存=新整数[(高-低)1];
int j=低电平;
for(int k=0;k cache.lengthk)
缓存[k]=新整数(j)和:
//必须保留范围[-128,127](jls 7 5。1 .7)
断言IntegerCache.high=127
}
私有IntegerCache() {}
}
}
如上所示整数内部有一个私有静态类IntegerCache,该类静态初始化了一个包含了整数IntegerCache.low到Java。郎。整数。整数缓存。高的的整数数组。
其中Java。郎。整数。整数缓存。高的的取值范围在【127 ~整数。最大值-(-低)-1]之间。
在该区间内所有的Integer.valueOf(int)函数返回的对象,是根据(同国际组织)国际组织值计算的偏移量,从数组整数IntegerCache.cache中获取,对象是同一个,不会新建对象。
所以当我们修改了Integer.valueOf(1)的价值后,所有整数整数缓存。缓存[1-整数缓存。低]的返回值都会变更。
我相信你们的智商应该理解了,如果不理解请在评论区拨打10086 .
好了,那么不在[整数缓存。低~整数缓存。高]的部分呢?
很显然,它们是幸运的,没有被IntegerCache缓存到,法外之民,每次它们的到来,都会新的一边,在虚拟机(Java虚拟机的缩写)上分配一块土(内)地(存)。
遐想
如果我把转换的参数换成类型换成(同国际组织)国际组织呢?
公共静态void testOne()引发异常{
int a=1,b=2;
swapOne(a,b);
System.out.println('a=' a ',b=' b);
}
静态void swapOne(int a,int b){
//需要实现的部分
}
以作者目前的功力,无解。高手可以公众号留言,万分感谢!
至此交换部分已经讲完了。
1 + 1
首先让我们来看一下代码:
公共静态void testOne() {
int one=1;
int two=one one
System.out.printf('Two=%d ',Two);
}
请问输出是什么?
如果你肯定的说是2,那么你上面是白学了,请直接拨打95169。
我可以肯定的告诉你,它可以是【整数. MIN _ VALUE ~整数. MAX_VALUE]区间的任意一个值。
惊喜不惊喜!意外不意外!刺激不刺激!
让我们再撸(捋)一(一)串(遍)烧(代)烤(码)。
作者使用集成驱动电子设备工具,直接反编译了这个。班级文件
公共静态void testOne() {
int one=1;
int two=one one
System.out.printf('Two=%d ',Two);
}
这里的变量二竟然没有调用Integer.valueOf(int),跟想象的不太一样,我怀疑这是集成驱动电子设备的锅。
所以果断查看编译后的字节码。以下为摘录的部分字节码:
LDC 'Two=%d '
ICONST_1
一个Java/语言/对象数组
DUP
ICONST_0
ILOAD 2
调用静态Java/lang/Integer。(I)Ljava/lang/Integer的值;
AASTORE
INVOKEVIRTUAL Java/io/printstream。printf(Ljava/lang/String;【Ljava/lang/Object;)Ljava/io/PrintStream;
购买凭证(购买证明)
可以看出确实是集成驱动电子设备的锅,这里不仅调用了一次Integer.valueOf(int),而且还创建一个目标的数组。
完整的Java 语言(一种计算机语言,尤用于创建网站)语言(一种计算机语言,尤用于创建网站)代码应该是如下所示:
公共静态void testOne() {
int one=1;
int two=one one
object[]参数={ integer。值为(二)};
System.out.printf('Two=%d ',params);
}
所以只要在方法调用前修改整数IntegerCache.cache[2 128]的值就可以了,所以在类的静态初始化部分加些代码。
公共类OnePlusOne {
静态{
尝试{
班级?cacheClazz=class . forname(' Java . lang . integer $ integer cache ');
field cache field=cacheclazz . getdeclaredfield(' cache ');
cachefield . set accessible(true);
Integer[]cache=(Integer[])cache field . get(null);
//这里修改为1 1=3。
cache[2 128]=新整数(3);
} catch(异常e) {
e . printstacktrace();
}
}
公共静态void testOne() {
int one=1;
int two=one one
System.out.printf('Two=%d ',Two);
}
}
two == 2 ?
修改integer . integer cache . cache[2 ^ 128]的值后,变量二是否仍然等于2?
公共静态void testTwo() {
int one=1;
int two=one one
system . out . println(two==2);
system . out . println(integer . value of(two)==2);
}
上面的代码输出如下
真实的
错误的
因为two==2不涉及整数装箱的变换,也不涉及原类型的比较,所以原类型的2始终等于2。
Integer.valueOf(two)==2的真正形式是Integer。valueof(二)。Intvalue==2,即3==2,所以为假。
这里可以看到,如果将一个值为null的整型变量与一个带双等号的int变量进行比较,就会抛出NullPointException。
这里的方法如果改成System.out.println('Two=' two)的形式会有什么样的输出?你可以试试。
后记
XCache
种类
有缓存吗?
最小值
最高的
布尔代数学体系的
没有
-
-
字节
字节缓存
-128
27(固定)
短的
ShortCache
-128
27(固定)
性格;角色;字母
字符缓存
0
27(固定)
整数
IntegerCache
-128
Java . lang . integer . integer cache . high
长的
LongCache
-128
27(固定)
浮动
没有
-
-
两倍
没有
-
-
java.lang.Integer.IntegerCache.high
看了IntegerCache类的方法sun.misc.VM.getSavedProperty来high,可能会有以下疑问。我们不会拖延,采取一问一答的方式。
1.这个值是如何传递给JVM的?
与系统属性一样,它是在JVM启动时通过设置-DJ ava . lang . integer . integer cache . high=XXX来传递的。
2.这个方法和System.getProperty有什么区别?
为了区分JVM系统需要的参数和用户使用的参数,
启动时,Java . lang . system . initializesystemclass会将启动参数保存在两个位置:
2.1 sun.misc.VM.savedProps保存JVM收到的所有系统参数。
启动时,JVM将调用Java . lang . system . initializesystemclass方法来初始化该属性。
同时,将调用sun . misc . VM . saveandmoveproperties方法从java.lang.System.props中删除以下属性:
sun.nio.MaxDirectMemorySize
sun.nio.PageAlignDirectMemory
sun . lang . class loader . allowarray语法
Java . lang . integer . integer cache . high
sun.zip.disableMemoryMapping
sun.java .启动器.诊断
上面列出的属性都是JVM启动时需要设置的系统参数,所以为了安全和隔离,它们与用户可访问的System.props是分开的。
2.2 java.lang.System.props除了JVM启动所需的以下参数外,还存储其他参数。
sun.nio.MaxDirectMemorySize
sun.nio.PageAlignDirectMemory
sun . lang . class loader . allowarray语法
Java . lang . integer . integer cache . high
sun.zip.disableMemoryMapping
sun.java .启动器.诊断
PS:作者使用的JDK 1.8.0_91
Java 9的IntegerCache
试想一下,如果上述调皮的玩法出现在某个第三方的依赖包里,绝对会有一群程序员发疯(请不要尝试这么烂的玩法,后果很严重)。
幸运的是,Java 9限制了这一点。Module-info.java文件可以写在相应的模块中,这就限制了使用反射来访问成员等。按要求声明后,只有当类在同一个模块中,或者模块打开包进行反射访问时,代码才能访问反射可以访问的字段、方法和其他信息。详情请参考文章:
在Java 9中修改IntegerCache?
感谢莉迪亚和飞鸟的宝贵建议和辛苦校对。
最后跟大家分享一个java中Integer值比较不注意的问题:
让我们先来看一段代码:
公共静态void main(String[] args) {
integer a1=integer . value of(60);//danielinbiti
整数b1=60
system . out . println(' 1:='(a1==B1));
整数a2=60
整数b2=60
system . out . println(' 2:='(a2==B2));
整数a3=新整数(60);
整数b3=60
system . out . println(' 3:='(a3==B3));
整数a4=129
整数b4=129
system . out . println(' 4:='(a4==B4));
}
如果不执行这段代码的比较结果,不知道你脑子里的答案是什么。
要知道这个答案,涉及到Java缓冲区和堆的问题。
对于-128和127之间的数字,Java整数类型取自缓冲区,因此与等号比较是一致的。但是对于不在这个范围内的数字,它们在堆中是新的。所以地址空间不一样,所以不相等。
Integer b3=60,这是一个打包过程,即Integer b3=Integer.valueOf(60)
所以以后遇到整数比较值是否相等时,需要使用intValue()。
双精度没有缓冲。
回答
1:=真
2:=真
3:=假
4:=假
总结
这就是本文的全部内容。希望这篇文章的内容对你的学习或工作有一定的参考价值。有问题可以留言交流。谢谢你的支持。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。