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); }
讯享网
不过修改这个缓存会比较危险,不介意。谁知道什么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); }
理解了装箱、缓存、引用就不难理解了。可以自己试试。
先来点基础的知识
讯享网 基本类型和包装类的对应 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 -----------
由于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 -----------
超过了byte的取值范围就会在创建新对象
自动装箱其底层会调用valueOf()方法,简单源码分析(JDK1.8):
public final class Integer extends java八中基础类型 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种基本类型的包装类和对象池
扩展知识
在JVM中,类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载7个阶段。而解析阶段即是虚拟机将常量池内的符号引用替换为直接引用的过程。
总结
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/8869.html