Java基础之Integer使用的注意事项及面试题

 更新时间:2017年12月05日 12:02:56   作者:Oh-Smile  
这篇文章主要给大家介绍了关于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个阶段。而解析阶段即是虚拟机将常量池内的符号引用替换为直接引用的过程。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

相关文章

  • springboot默认的5种加载路径详解

    springboot默认的5种加载路径详解

    这篇文章主要给大家介绍了关于springboot默认的5种加载路径,文中通过示例代码介绍的非常详细,对大家学习或者使用springboot具有一定的参考学习价值,需要的朋友可以参考下
    2022-05-05
  • 详解Spring注解驱动开发之属性赋值

    详解Spring注解驱动开发之属性赋值

    今天带大家学习Spring注解驱动开发的相关知识,文中有非常详细的代码示例,对正在学习Java的小伙伴们很有帮助,需要的朋友可以参考下
    2021-05-05
  • Java创建表格实例详解

    Java创建表格实例详解

    这篇文章主要介绍了Java创建表格实例详解,需要的朋友可以参考下。
    2017-09-09
  • java实现哈夫曼文件解压缩

    java实现哈夫曼文件解压缩

    这篇文章主要为大家详细介绍了java实现哈夫曼文件解压缩,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • Spring boot从安装到交互功能实现零基础全程详解

    Spring boot从安装到交互功能实现零基础全程详解

    这篇文章主要介绍了Spring boot从安装到交互功能得实现全程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • Java Stream对象并行处理方法parallel()代码示例

    Java Stream对象并行处理方法parallel()代码示例

    在Java中Stream是一种用于处理集合数据的流式操作API,它提供了一种简洁、灵活、高效的方式来对集合进行各种操作,下面这篇文章主要给大家介绍了关于Java Stream对象并行处理方法parallel()的相关资料,需要的朋友可以参考下
    2023-11-11
  • Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验 使用消息资源文件对消息国际化

    Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验

    这篇文章主要介绍了Springboot 使用 JSR 303 对 Controller 控制层校验及 Service 服务层 AOP 校验 使用消息资源文件对消息国际化的相关知识,需要的朋友可以参考下
    2017-12-12
  • Java数据开发辅助工具Docker与普通程序使用方法

    Java数据开发辅助工具Docker与普通程序使用方法

    这是为数据开发人员使用的辅助工具,用于数据库之间的表同步,说同步并不严谨,因为不是实时更新的,更确切的说法是复制,可以方便的从一个数据库复制表到另一个数据库,以下遇到同步的词请理解为复制
    2021-09-09
  • 基于FLink实现实时安全检测的示例代码

    基于FLink实现实时安全检测的示例代码

    这篇文章主要为大家详细介绍了如何基于FLink实现实时安全检测的功能,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的可以了解一下
    2023-02-02
  • Java创建型模式之建造者模式详解

    Java创建型模式之建造者模式详解

    建造者模式,是一种对象构建模式 它可以将复杂对象的建造过程抽象出来,使这个抽象过程的不同实现方法可以构造出不同表现的对象。本文将通过示例讲解建造者模式,需要的可以参考一下
    2023-02-02

最新评论