Java的八种基本类型都有对应的包装类,包装类内部有一个实例变量,保存对应的基本类型的值,这个类一般还有一些静态方法、静态变量和实例方法,以方便对数据进行操作。
包装类的类名除了Integer和Character外,其他类名称与基本类型基本一样,只是首字母大写。
包装类与基本类型的转换代码结构是类似的,每种包装类都有一个静态方法valueOf(),接受基本
类型,返回引用类型,也都有一个实例方法xxxValue()返回对应的基本类型。
以Integer和int转换为例:
int i = 123;
Integer ie = Integer.valueOf(i); // 装包,静态方法传入int
int j = ie.intValue(); // 拆包,Integer对象获取值
Java5 后可以自动装包和拆包
Integer a = 100;
int b = a;
编译时编译器将上面的代码替换为
Integer a = Integer.valueOf(100);
int b = a.intValue();
另外包装类也可以直接使用构造方法来创建
Integer a = new Integer(100);
一般建议使用valueOf方法。因为new每次都会创建一个新对象,而除了Float和Double外的其他包装类,都会缓存包装类对象,减少需要创建对象的次数,节省空间,提升性能。实际上,从Java9开始,这些构造方法已经被标记为过时了,推荐使用静态的valueOf方法。
所有包装类都重写了Object类的如下方法:
boolean equals(Object obj)
int hashCode()
String toString()
其中equals和hashCode绑定
equals用于判断当前对象和参数传入的对象是否相同,Object类的默认实现是比较地址,对于两个变量,只有这两个变量指向同一个对象时,equals才返回true,它和比较运算符(==)的结果是一样的。
然而equals应该反映的是对象间的逻辑相等关系,所以这个默认实现一般是不合适的,子类需要重写该实现。所有包装类都重写了该实现,实际比较用的是其包装的基本类型值
public boolean equals(Object obj) {
if(obj instanceof Integer) {
return value == ((Integer)obj).IntegerValue();
}
return false;
}
Float有一个静态方法floatToIntBits(),将float的二进制表示看作int。需要注意的是,只有两个float的二进制表示完全一样的时候,equals才会返回true。
Double的equals方法与Float类似,它有一个静态方法doubleToLongBits,将double的二进制表示看作long,然后再按long比较。
hashCode返回一个对象的哈希值。哈希值是一个int类型的数,由对象中一般不变的属性映射得来,用于快速对对象进行区分、分组等。一个对象的哈希值不能改变,相同对象的哈希值必须一样。不同对象的哈希值一般应不同,但可以有对象不同但哈希值相同的情况。
包装类都重写了hashCode,根据包装的基本类型值计算hashCode,对于Byte、Short、Integer、Character,hashCode就是其内部值
public int hashCode() {
return (int)value;
}
对于Boolean,因为只有true和false,选用两个质数作为哈希值,减少哈希冲突
public int hashCode() {
return value ? 1231 : 1237;
}
对于Float,hashCode为int值
public int hashCode() {
return floatToIntBits(value);
}
对于Long,hashCode为高32位与低32位进行位异或操作
无符号右移操作符(>>>)
public int hashCode() {
return(int)(value ^ (value >>> 32));
}
Comparable接口只有一个方法compareTo,当前对象与参数对象进行比较,在小于、等于、大于参数时,应分别返回-1、0、1。
对于Boolean,false小于true。
对于Float和Double,存在和equals方法一样的问题,0.01和0.1*0.1相比的结果并不为0。
public interface Comparable {
public int compareTo(T o);
}
除了toString方法外,包装类还有一些其他与String相关的方法。除了Character外,每个包装类都有一个静态的valueOf(String)方法,根据字符串表示返回包装类对象
Boolean b = Boolean.valueOf("true");
还有一个静态的parseXXX(String)方法,根据字符串表示返回基本类型值
boolean b = Boolean. parseBoolean("true");
转化为String有一个静态的toString方法,根据基本类型值返回字符串表示
System.out. println(Boolean.toString(true));
输出true
Boolean的TRUE和FALSE
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
所有数值类型都定义了最大值和最小值,对于Integer,在Java中,int类型占用32位,它能够表示的最小值为-2^31(0x80000000),最大值为2^31-1(0x7fffffff)。
public static final int MIN_VALUE = 0x80000000;
public static final int MAX_VALUE = 0x7fffffff;
Float和Double还定义了正无穷、负无穷、非数值,对于Double类
public static final double POSITIVE_INFINITY = 1.0 / 0.0; //正无穷
public static final double NEGATIVE_INFINITY = -1.0 / 0.0; //负无穷
public static final double NaN = 0.0d / 0.0; //非数值
6种数值类型包装类有一个共同的父类Number。Number是一个抽象类,它定义了如下方法
byte byteValue()
short shortValue()
int intValue()
long longValue()
float floatValue()
double doublevalue()
因此包装类可以返回任意的数值类型
不可变不用操心数据被意外改写的可能,使得程序更为简单安全,可以安全地共享数据,尤其是在多线程的环境下。包装类都是不可变类,实例对象一旦创建,就没有办法修改了。
这是通过如下方式强制实现的:
·所有包装类都声明为了final,不能被继承。
·内部基本类型值是私有的,且声明为了final。
·没有定义setter方法。