装箱:将基本数据类型变成包装类
拆箱:将包装类变成基本数据类型
那么如何实现装箱和拆箱呢,从Java SE5开始就提供了自动装箱的特性,所以输入以下程序即可,如
Integer i = 15;//装箱
有了装箱那么怎么拆箱呢,如下
Integer i = 15;//装箱
int n = i;//拆箱
下表是基本数据类型对应的包装器类型
基本数据类型 | 包装类型 |
---|---|
byte(1个字节) | Byte |
char(2个字节) | Character |
short(2个字节) | Short |
int(4个字节) | Integer |
long(8个字节) | Long |
float(4个字节) | Float |
double(8个字节) | Double |
boolean(未指定) | Boolean |
自动装箱和拆箱是如何实现的呢?我们先输入以下代码
public class wy1 {
public static void main(String[]args){
Integer i = 15;//装箱
int n = i;//拆箱
}
}
编译运行后反编译class文件,得到以下反编译
我们从中可以看到装箱时所用的是valueOf的方法
拆箱所用的是intvalue的方法
那么valueOf方法是怎样的呢?
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
low表示最小值为-128,high表示最大值为127
Cache为缓存
意思是在-128~127内的数据会存储在缓存中,当数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;
public class Wy1 {
public static void main(String[] args) {
Integer a = 125;
Integer b = 125;
System.out.println(a == b);
}
}
此时所输出的为true,是因为125在[-128,127]之间,是cache中已经存在的对象肯定是相同的,所指的是同一对象
但是一旦超出范围,如
public class Wy1 {
public static void main(String[] args) {
Integer c = 130;
Integer d = 130;
System.out.println(c == d);
}
}
此时所输出的结果为false;这是为什么呢?我们需要了解IntegerCache类的实现:
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) {
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);
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
从代码中可以看出,如果数值是在[-128~127]之间,那么会在缓存中返回指向已存储的对象,否则需要新建一个Integer对象
c和d的值为130,所以指的是不同的对象
那么我们看以下代码
public class Wy1 {
public static void main(String[] args) {
Double e = 100.0;
Double f = 100.0;
System.out.println(e == f);
}
}
此时输出的结果为false,这是因为此时采用了DoublevalueOf的方法
public static Double valueOf(String s) throws NumberFormatException {
return new Double(FloatingDecimal.readJavaFormatString(s).doubleValue());
}
valueOf方法在返回的生活new Double(),所以返回的是新建的一个Double对象,会显示false。
我们再看如下代码:
public class Wy1 {
public static void main(String[] args) {
Boolean g = false;
Boolean h = false;
Boolean i = true;
Boolean j = true;
System.out.println(g == h);
System.out.println(i == j);
}
}
此时的输出结果为true true,这又是为什么呢?我们来查看一下Boolean.valueOf的源码
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
对象相等比较
“==”可以用于原始值进行比较,也可以用于对象进行比较,当用于对象与对象之间比较时,比较的不是对象代表的值,而是检查两个对象是否是同一对象,这个比较过程中没有自动装箱发生。进行对象值比较不应该使用”==”,而应该使用对象对应的equals方法。
对于”==”,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;如果作用于引用类型的变量,则比较的是所指向的对象的地址是否相同。
对于equals,其对于String源码如下
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
其中instanceof是比较类型的意思,我们来看道题
假设有以下代码
String s = "hello";
String t = "hello";
char c[] = {'h', 'e', 'l', 'l', 'o'};
s.equals(t);
t.equals(c);
s==t;
t.equals(new String (“hello”));
t.equals(c);应为false
在采用equals方法时,我们要分以下步骤来分析结果:
1.先比较是否都是引用类型,引用相等直接true
否则的话:
①.比较类型
②.比较长度
③.把string转成char[], 依次比较每一个字符,全部相等则为true,否则为false。