那些坑爹的比较
一般的数值类型的比较用==就可以了,但其他情况就需要注意了。
实例的比较
对两个对象实例的比较不能使用==,必须使用equal()。尤其要注意字符串、数组、对象实例。
public class Main {public static void main(String[] args) {String s1 = "hello";String s2 = "HELLO".toLowerCase();System.out.println(s1 == s2);System.out.println(s1.equals(s2));}}# outputfalsetrue
BigDecimal类型的比较
建议使用compareTo()方法比较,因为使用equals()方法不但要求两个BigDecimal的值相等,还要求它们的scale()相等:
BigDecimal d1 = new BigDecimal("123.456");BigDecimal d2 = new BigDecimal("123.45600");System.out.println(d1.equals(d2)); // false,因为scale不同System.out.println(d1.equals(d2.stripTrailingZeros())); // true,因为d2去除尾部0后scale变为2System.out.println(d1.compareTo(d2)); // 0
必须使用compareTo()方法来比较,它根据两个值的大小分别返回负数、正数和0,分别表示小于、大于和等于。
静态工厂方法
我们把能创建“新”对象的静态方法称为静态工厂方法。Integer.valueOf()就是静态工厂方法,它尽可能地返回缓存的实例以节省内存。当然这也意味着创建的多个对象引用的可能是同一个实例。
Integer m = Integer.valueOf(3);Integer n = Integer.valueOf(3);Integer o = Integer.valueOf(3889);Integer p = Integer.valueOf(3889);// 打印各引用的内存地址System.out.println(System.identityHashCode(m)); //5592464System.out.println(System.identityHashCode(n)); //5592464System.out.println(System.identityHashCode(o)); //1830712962System.out.println(System.identityHashCode(p)); //1112280004
所以我们创建新对象时,优先选用静态工厂方法而不是new操作符。
内存中的数字表示
byte类型在内存中表示
byte型的-1在内存中的二进制表示是11111111,第一位是高位,亦是符号位。如果我们将它转换为无符号值,则是255。
byte x = -1;byte y = 127;System.out.println(Byte.toUnsignedInt(x)); // 255System.out.println(Byte.toUnsignedInt(y)); // 127
浮点型数值在内存中的表示
在学习java的过程中遇到一个问题,float的取值范围比long大得多,可达10的38次方,可float只占用四个字节,long占用8个字节。
原因在于浮点类型在内存中的存储方式与整型相去甚远。float使用了IEEE 754标准中的binary32表示,double使用的是binary64。
首先我们要理解内存中的小数表示,以16.625为例,转化为二进制,则整数部分为10000,那么小数部分呢?
我们反过来看,一个二进制数10000.101的十进制为多少?要注意,这里的小数点两边相差2倍,而非10倍。所以转化为二进制应该为16.625。
那么关键点来了,通常我们希望浮点数有尽可能多的有效位,于是我们考虑了一些折中的策略。以10000.101为例,我们可以借鉴十进制的科学计数法,将之记为1.0000101E100。由于整数部分一定为1,所以需要存储的只有小数和指数部分,再加上符号位。
内存中是这样存储的:
S为一位的符号位,0为正,1为负。E为8为的指数为,M为23为的小数位。需要注意的是,E是有符号的,所以取值范围为-127~127。网上有说E并没有符号的设置,而是通过实际值十进制(可能为负值)+127在转换为二进制赋值给E存储,取出时则是转换后再减去127。
按这种实现方式,16.625在内存中为01000001 10000101 00000000 00000000。
回过头来,显然float的取值范围为1.1111 1111 1111 1111 1111 1111 1111 111E1111 111正负之间(即约为-2^128到2^128,当然负值应该比正值多一个值)
