文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Java基础之Integer使用的注意事项是什么

2023-05-30 19:10

关注

这篇文章主要介绍了Java基础之Integer使用的注意事项是什么,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

JAVA中Integer对象的引用

JAVA中没有指针一说,但也有引用的概念。这里要说的主要是Integer是不是同一个对象。

1、先看一段代码:

public static void main(String[] args){ Integer a1 = 100; Integer b1 = a1;//另一种也可以b1=100 Field field = null; try { field = a1.getClass().getDeclaredField("value"); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } field.setAccessible(true); try { field.set(a1, 5000); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("b1="+b1); Integer c1 = 100; System.out.println("c1="+c1); }

结果:

b1=5000

c1=5000

从上面,首先这里要说明几个,

1)、对于Integer来说,-128-127之间的整型已经初始化放在IntegerCache中,如果是装箱的话,就会从这里面取对象。

2)、b1=a1到底是数字赋值还是同一个对象?这个从结果实际就可以看出来,b1和a1指向同一个对象,而不是同一个数值

3)、c1=100,说明对于-128-127之间的数值,都是从IntegerCache中获取的对象,100对应的Integer对象被改变后,后续对于100的装箱都被改变。因为获取cache中对象时用的是数组索引,而不是数值比较获取的。

不过修改这个缓存会比较危险,不介意。谁知道什么jar包或者什么平台来个100的装箱,但得到结果又不是100,到时就崩溃了。

2、通过上面描述,那么如果改成这样又是什么答案

public static void main(String[] args){ Integer a1 = 200; Integer b1 = a1; Field field = null; try { field = a1.getClass().getDeclaredField("value"); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } field.setAccessible(true); try { field.set(a1, 5000); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("b1="+b1); Integer c1 = 200; System.out.println("c1="+c1); }

3、那么再改一下

public static void main(String[] args){ Integer a1 = new Integer(100); Integer b1 = a1; Field field = null; try { field = a1.getClass().getDeclaredField("value"); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } field.setAccessible(true); try { field.set(a1, 5000); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("b1="+b1); Integer c1 = 100; System.out.println("c1="+c1); }

这又是什么答案。对于new的操作,是不进行装箱的,而是在堆中生成对象的。

理解了装箱、缓存、引用就不难理解了。可以自己试试。

先来点基础的知识

   基本类型和包装类的对应   byte  Byte   short  Short   int  Integer   long  Long   float  Float   double  Double   char  Character   boolean  Boolean

上述的八中基本数据类型的对应关系只有 int->Integer    char->Character    两个变化较大,其余都只是将首字母转换为小写。
再来了解一下JDK5的新特性:自动装箱和拆箱

自动装箱:把基本类型转换为包装类类型

自动拆箱:把包装类类型转换为基本类型

public class Demo_Integer {  public static void main(String[] args) { //JDK1.5之前  int a = 100;  Integer a1 = new Integer(a); //将基本数据类型包装成对象,装箱  int b = a1.intValue(); //将对象转换为基本数据类型,拆箱 //JDK1.5之后  int x = 100;  Integer x1 = x;  //自动装箱,把基本数据类型转换为对象  int y = x1 + x;  //自动拆箱,把对象转换为基本数据类型  } }

注意事项

public class Demo_Integer {  public static void main(String[] args) {   Integer a = null;   int b = a + 100; //自动拆箱底层将会调用a.intValue(),a为null,自然会抛出 NullPointerException   System.out.println(b);  } }

面试题

public class Demo_Integer {  public static void main(String[] args) {   Integer i1 = new Integer(97);   Integer i2 = new Integer(97);   System.out.println(i1 == i2);   System.out.println(i1.equals(i2));   System.out.println("-----------");     Integer i3 = new Integer(197);   Integer i4 = new Integer(197);   System.out.println(i3 == i4);   System.out.println(i3.equals(i4));   System.out.println("-----------");  } }
Output:  false  true  -----------  false  true  -----------

原因:  

    new 是在堆内存开辟空间的,自然比较地址值(==)都为false.  

    由于Integer重写了equals方法,所以equals输出都为true. 

你可能感觉太简单了,没有任何技术含量,因为上面的不是重点,看下面代码

public class Demo_Integer {  public static void main(String[] args) {   Integer i1 = 127;   Integer i2 = 127;   System.out.println(i1 == i2);   System.out.println(i1.equals(i2));   System.out.println("-----------");    Integer i3 = 128;   Integer i4 = 128;   System.out.println(i3 == i4);   System.out.println(i3.equals(i4));   System.out.println("-----------");  } }
Output: true true ----------- false true -----------

原因:  

    为什么当int大于127就是两个对象,127这个数字是不是觉得很熟悉?  

    -128到127是byte的取值范围,如果在这个取值范围内,自动装箱就不会创建新对象了,而从常量池中获取  

    超过了byte的取值范围就会在创建新对象 

自动装箱其底层会调用valueOf()方法,简单源码分析(JDK1.8):

public final class Integer extends Number implements Comparable<Integer> {  public static Integer valueOf(int i) {   //当 i >= -128 且 i <= 127 时,会直接将取缓冲区中的对象   if (i >= IntegerCache.low && i <= IntegerCache.high)    return IntegerCache.cache[i + (-IntegerCache.low)];   return new Integer(i);//超过了byte取值范围会在堆内存创建  }   //内部类充当缓冲区  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() {}  }   }

8种基本类型的包装类和对象池

java中基本类型的包装类的大部分都实现了常量池技术,这些类是Byte,Short,Integer,Long,Character,Boolean,另外两种浮点数类型的包装类则没有实现。另外Byte,Short,Integer,Long,Character这5种整型的包装类也只是在对应值小于等于127时才可使用对象池,也即对象不负责创建和管理大于127的这些类的对象

扩展知识

在jvm规范中,每个类型都有自己的常量池。常量池是某类型所用常量的一个有序集合,包括直接常量(基本类型,String)和对其他类型、字段、方法的符号引用。之所以是符号引用而不是像c语言那样,编译时直接指定其他类型,是因为java是动态绑定的,只有在运行时根据某些规则才能确定具体依赖的类型实例,这正是java实现多态的基础。

在JVM中,类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载7个阶段。而解析阶段即是虚拟机将常量池内的符号引用替换为直接引用的过程。

感谢你能够认真阅读完这篇文章,希望小编分享的“Java基础之Integer使用的注意事项是什么”这篇文章对大家有帮助,同时也希望大家多多支持编程网,关注编程网行业资讯频道,更多相关知识等着你来学习!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯