包装类是什么呢?
它是一个类,内部有一个实例变量,保存对应的基本类型的值, 这个类一般还有一些静态方法、静态变量和实例方法,以方便对数据进行操作。
-
八种基本类型,对应的包装类
image.png
基本类型和包装类
- 装箱
将基本类型转换为包装类的过程
- 拆箱
将包装类型转换为基本类型的过程
自动装箱和拆箱
Java 1.5
以后引入,可以直接将基本类型赋值给引用类型,反之亦可
Integer a = 100;
int b = a;
Integer a = Integer.valueOf(100);
int b = a.intValue();
自动装箱/拆箱是Java编译器提供的能力,背后,它会替换为调用对应的valueOf()/xxxValue()
可以通过new创建
Integer a = new Integer(100);
Boolean b = new Boolean(true);
Double d = new Double(12.345);
Character c = new Character('马');
那到底应该用静态的valueOf方法,还是使用new呢?
般建议使用valueOf
new每次都会创建一个新对象,而除了Float和Double外的其他包装类, 都会缓存包装类对象,减少需要创建对象的次数,节省空间,提升性能
重写Object方法
- equals
equals用于判断当前对象和参数传入的对象是否相同,Object类的默认实现是比较址, 对于两个变量,只有这两个变量指向同一个对象时,equals才返回true,它和比较运算符(==)的结果是一样的。
equals应该反映的是对象间的逻辑相等关系
Long
public boolean equals(Object obj) {
if (obj instanceof Long) {
return value == ((Long)obj).longValue();
}
return false;
}
Float
public boolean equals(Object obj) {
return (obj instanceof Float)
&& (floatToIntBits(((Float)obj).value) == floatToIntBits(value));
}
Float有一个静态方法floatToIntBits(),将float的二进制表示看做int。 需要注意的是,只有两个float的二进制表示完全一样的时候,equals才会返回true
Double的equals方法与Float类似,它有一个静态方法doubleToLongBits,将double的二进制表示看做long,然后再按long比较,数值不精确
- hashCode
hashCode返回一个对象的哈希值,哈希值是一个int类型的数,由对象中一般不变的属性映射得来,用于快速对对象进行区分、分组等。一个对象的哈希值不能变,相同对象的哈希值必须一样。不同对象的哈希值一般应不同,但这不是必须的,可以有不同对象但哈希值相同的情况。
hashCode和equals方法联系密切,对两个对象,如果equals方法返回true,则hashCode也必须一样。反之不要求
子类重写equals时,也必须重写hashCode
之所以有这个约定,是因为Java API中很多类依赖于这个行为,尤其是集合中的一些类
Byte, Short, Integer, Character,hashCode就是其内部值
public int hashCode() {
return (int)value;
}
Boolean
public int hashCode() {
return value ? 1231 : 1237;
}
Long
public int hashCode() {
return (int)(value ^ (value >>> 32));
}
是高32位与低32位进行位异或操作
Float
public int hashCode() {
return floatToIntBits(value);
}
Double
public int hashCode() {
long bits = doubleToLongBits(value);
return (int)(bits ^ (bits >>> 32));
}
- toString
每个包装类也都重写了toString方法,返回对象的字符串表示 - Comparable
个包装类也都实现了Java API中的Comparable接口
public interface Comparable<T> {
public int compareTo(T o);
}
<T>是泛型语法,我们后续文章介绍,T表示比较的类型,由实现接口的类传入。 接口只有一个方法compareTo,当前对象与参数对象进行比较,在小于、等于、大于参数时,应分别返回-1,0,1
对于Float和Double,存在和equals一样的问题,0.01和0.10.1相比的结果并不为0*
- 包装类和String
除了toString方法外,包装类还有一些其他与String相关的方法
System.out.println(Integer.toBinaryString(12345)); //输出2进制
System.out.println(Integer.toHexString(12345)); //输出16进制
System.out.println(Integer.parseInt("3039", 16)); //按16进制解析
11000000111001
3039
12345
常用常量
Boolean类型
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false)
Integer
public static final int MIN_VALUE = 0x80000000;
public static final int MAX_VALUE = 0x7fffffff;
Float和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;
Number
六种数值类型包装类有一个共同的父类Number
抽象类
方法
byte byteValue()
short shortValue()
int intValue()
long longValue()
float floatValue()
double doubleValue()
不可变性
包装类都是不可变类
这是通过如下方式强制实现的:
所有包装类都声明为了final,不能被继承
内部基本类型值是私有的,且声明为了final
没有定义setter方法
不可变使得程序可以更为简单安全,因为不用操心数据被意外改写的可能了,可以安全的共享数据,尤其是在多线程的环境下
网友评论