写给小白看的Java基础知识,阅读本文大概需要7分钟
Java中有8种基础数据类型,boolean,char,byte,short,int,long,float,double。从jdk5开始提供了自动装箱拆箱机制,对应的包装类型即Boolean,Character,Byte,Short,Integer,Long,Float,Double。
首先解释一下为什么要引入装箱和拆箱机制,因为Java是面向对象的语言啊,这样使用了包装类后,就可以调用object的一些方法了。都是个人见解,欢迎指正。
Integer i=10;//装箱int n=i;//拆箱
装箱就是将基础数据类型转换为对应的包装器类型;
拆箱就是将包装器类型转换为对应的基础数据类型;
那装箱和拆箱是如何实现的呢,其实我们在Integer源码中可以查看,装箱使用了valueOf()方法,拆箱使用了intValue()。
public static Integer valueOf(int i) {
//low=-128
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
public int intValue() {
return value;
}
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() {}
}
从上述方法的具体实现可以知道,vauleOf已经在cache中创建了[-128,127]范围的对象数组,当新建的Integer数值在该范围中,会从对象数组里返回相应的对象。如果超出范围会重新创建一个对象。
经过上面的解释我们可以很好地理解上图的结果,i1和i2都在[-128,127]中,所以返回的是同一个对象,结果为true。而i3和i4超出该范围,所以两次都要新建对象,于是结果返回false。
而对于其他几种包装类型,也都是利用对应的vauleOf和(Boolean/Character/Byte/Short/Long/Float/Double)Value方法实现装箱,拆箱。其中Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的,Double、Float的valueOf方法的实现是类似的,大家可以在源码中查看。
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 200;
Integer f = 200;
Long g = 3L;
Long h = 2L;
System.out.println(c==d);//true
System.out.println(e==f);//false
System.out.println(c==(a+b));//true
System.out.println(c.equals(a+b));//true
System.out.println(g==(a+b));//true 当==两边有算式时,就比较数值(自动拆箱)
System.out.println(g.equals(a+b));//false
System.out.println(g.equals(a+h));//true
在解释结果前先来说说==和euqals的区别:
== : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不是同一个对象(基本数据类型比较的是值,引用数据类型比较的是内存地址)。
equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况:
情况 1:类没有覆盖 equals() 方法。则通过 equals() 比较该类的两个对象时,等价于通过“==”比较这两个对象。
情况 2:类覆盖了 equals() 方法。一般,我们都覆盖 equals() 方法来比较两个对象的内容是否相等;若它们的内容相等,则返回 true (即,认为这两个对象相等)。
这里解释一下后三个的结果,==两边如果有算式的话,那就只比较内容而不是地址,结果为true。倒数第二个中,a+b和g的类型不同,自然地址也不相同,结果为false。最后一个a+h结果会发生隐式转换,所以结果为true。
----------------------------------------------------------------------------------------------
欢迎关注我的公众号预备码农