java中integer的用法,Java Integer,关于Java中你所不知道的Integer详解

java中integer的用法,Java Integer,关于Java中你所不知道的Integer详解

本文主要介绍一些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的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: