一、包装类概述
Java中为8种基本数据类型对应准备了8种包装类型,8种包装类属于引用数据类型,父类是Object 8种基本数据类型对应的包装类型名:
1. Number
package java. lang;
public abstract class Number implements java. io. Serializable {
public abstract int intValue ( ) ;
public abstract long longValue ( ) ;
public abstract float floatValue ( ) ;
public abstract double doubleValue ( ) ;
public byte byteValue ( ) {
return ( byte ) intValue ( ) ;
}
public short shortValue ( ) {
return ( short ) intValue ( ) ;
}
private static final long serialVersionUID = - 8742448824652078965 L;
}
2. Number方法
以下方法所有的数字包装类的子类都有,但JDK1.5之后支持了自动装箱与拆箱,所以Number类中的方法就用不着了,以下只做简单说明
byte byteValue() 以 byte 形式返回指定的数值 abstract double doubleValue() 以 double 形式返回指定的数值 abstract float floatValue() 以 float 形式返回指定的数值 abstract int intValue() 以 int 形式返回指定的数值 abstract long longValue() 以 long 形式返回指定的数值 short shortValue() 以 short 形式返回指定的数值
二、 装箱与拆箱
1. 装箱与拆箱概述
装箱:将基本数据类型转换为包装器类型(引用数据类型) 拆箱:将包装器类型(引用数据类型)转换为基本数据类型 JDK1.5之后支持自动装箱与拆箱
public class Test {
public static void main ( String[ ] args) {
Integer x = new Integer ( 3 ) ;
int y = x. intValue ( ) ;
System. out. println ( y) ;
Integer a = 4 ;
int b = a;
System. out. println ( b) ;
}
}
NumberFormatException数字格式异常
public class Test {
public static void main ( String[ ] args) {
Integer i = new Integer ( "创建日期" ) ;
System. out. println ( i) ;
}
}
静态方法 static int parseInt(String s)
public class Test04 {
public static void main ( String[ ] args) {
String str = "123" ;
int i = Integer. parseInt ( str) ;
System. out. println ( i) ;
}
}
2. 源码解析
Java装箱过程是调用包装类的valueOf方法实现的,而拆箱过程则是调用包装类的xxxValue方法实现的(xxx代表对应的基本数据类型) 以Integer为例,判断以下代码的结果:
public class Test {
public static void main ( String[ ] args) {
Integer i1 = - 128 ;
Integer i2 = - 128 ;
Integer i3 = 100 ;
Integer i4 = 100 ;
Integer i5 = 127 ;
Integer i6 = 127 ;
Double d1 = 10.0 ;
Double d2 = 10.0 ;
Double d3 = 200.0 ;
Double d4 = 200.0 ;
System. out. println ( i1 == i2) ;
System. out. println ( i3 == i4) ;
System. out. println ( i5 == i6) ;
System. out. println ( d1 == d2) ;
System. out. println ( d3 == d4) ;
}
}
public static Integer valueOf ( int i) {
if ( i >= IntegerCache. low && i <= IntegerCache. high)
return IntegerCache. cache[ i + ( - IntegerCache. low) ] ;
return new Integer ( i) ;
}
Integer类的内部类IntegerCache源码:
private static class IntegerCache {
static final int low = - 128 ;
static final int high;
static final Integer cache[ ] ;
static {
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 ) ;
h = Math. min ( i, Integer. MAX_VALUE - ( - low) - 1 ) ;
} catch ( NumberFormatException nfe) {
}
}
high = h;
cache = new Integer [ ( high - low) + 1 ] ;
int j = low;
for ( int k = 0 ; k < cache. length; k++ )
cache[ k] = new Integer ( j++ ) ;
assert IntegerCache. high >= 127 ;
}
private IntegerCache ( ) { }
}
符合取值范围时,进入已创建好的静态IntergerCache中(预加载的缓存),i + (-IntegerCache.low)的值表示去取cache数组中那个下标的值 当不符合取值范围时,创建新的对象,即new开辟新的内存空间,此时不属于IntergerCache管理区 使用此方式的好处 : 尽管预加载缓存占用了部分内存,但为了更好地节约内存开销,在[-128,127]范围的Integer包装类型直接从预加载的缓存中去取,不在[-128,127]范围的则需要重新创建对象,即new开辟新的内存空间,如果没有缓存机制,那么只要是装箱,则需要全部声明新的Integer对象,即开辟更多的内存空间,会导致内存不断浪费 intValue()源码(联想byte、short、long、char):
public int intValue ( ) {
return value;
}
public static Boolean valueOf ( boolean b) {
return ( b ? TRUE : FALSE) ;
}
Double valueOf()源码(Float同理):
public static Double valueOf ( double d) {
return new Double ( d) ;
}
取值范围总结 : Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的 Double、Float的valueOf方法的实现是类似的,每次都返回不同的对象 Boolean单独
3. 装箱与拆箱时机
public class Test {
public static void main ( String[ ] args) {
Integer i1 = new Integer ( 100 ) ;
Integer i2 = new Integer ( 100 ) ;
Integer i3 = new Integer ( 0 ) ;
System. out. println ( i1 == i2) ;
System. out. println ( i1 == i2 + i3) ;
}
}
附、String、int、Integer相互转换
public class Test {
public static void main ( String[ ] args) {
int i1 = Integer. parseInt ( "100" ) ;
System. out. println ( i1 + 1 ) ;
String s2 = i1 + "" ;
System. out. println ( s2) ;
Integer x = 1000 ;
int y = x;
Integer k = Integer. valueOf ( "123" ) ;
String e = String. valueOf ( k) ;
}
}