Object
Object是所类的父类。
包装类
从性能上考虑,把常用数据存储到缓存区域,使用时不需要每次都创建新的对象,可以提高性能。
Byte、Short、Integer、Long:缓存范围[-128, 127];
Character: 缓存范围[0, 127];
BigDecimal
float和double都不能表示精确的小数,使用BigDecimal类可以解决该问题,BigDecimal用于处理金钱或任意精度要求高的数据。
基本运算
// 使用double类型
System.out.println(0.09 + 0.01); // 0.09999999999999999
// 使用BigDecimal类型double类型的构造器
BigDecimal num1 = new BigDecimal(0.09);
BigDecimal num2 = new BigDecimal(0.01);
System.out.println(num1.add(num2)); // 0.09999999999999999687749774324174723005853593349456787109375
// 使用BigDecimal类型String类型的构造器
BigDecimal num3 = new BigDecimal("0.09");
BigDecimal num4 = new BigDecimal("0.01");
System.out.println(num3.add(num4)); // 0.10
精度控制和除不尽问题
public static void main(String[] args) {
BigDecimal num1 = new BigDecimal("10.0");
BigDecimal num2 = new BigDecimal("3.0");
// 1. 保留位数和精度控制
// RoundingMode 舍入模式
// RoundingMode.HALF_UP 四舍五入
// RoundingMode.HALF_DOWN 四舍六入
BigDecimal r1 = num1.multiply(num2).setScale(2, RoundingMode.HALF_UP);
System.out.println("r1 = " + r1);
// 2. 除不尽问题
// java.lang.ArithmeticException
// Non-terminating decimal expansion; no exact representable decimal result.
// 报错原因:除不尽(3.333333333...333...)
BigDecimal r2 = num1.divide(num2, 3,RoundingMode.HALF_UP);
System.out.println("r2 = " + r2);
}
上述代码分别表示乘法和除法按照四舍五入方式保留两位小数。
String为什么是不可变的?
1. String类中使用final关键字修饰字符数组来保存字符串,private final char[] value, 所以String对象是不可变的。
2. String类也是用final修饰的,String不能被继承,所以String中的方法是不能被重写的
3. String类中只提供了可读方法。
String、StringBuilder、StringBuffer的区别
1. 可变性:
String类中使用final关键字修饰字符数组保存字符串,private final char[] value; String类也是final修饰,String不能被继承,String类中的方法不能被覆盖;String类中只提供了可读方法,所以String对象是不可变的。而StringBuilder和StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串char[] value但是没有用final关键字修饰,所以这两种对象都是可变的。
2. 线程安全性
StringBuilder对方法加了同步锁或者调用的方法加了同步锁,所以是线程安全的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。
3. 性能
每次对String类型进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String对象。StringBuffer每次都会对StringBuffer对象本身进行操作,而不是生成新的对象并改变对象引用。相同情况下使用StringBuilder相比使用StringBuffer仅能获得10%~15%左右的性能提升,但却要冒多线程不安全的风险。
对于三者使用的总结:
1. 操作少量的数据:适用String
2. 单线程操作字符串缓冲区下操作大量数据:适用StringBuilder
3. 多线程操作字符串缓冲区下操作大量数据:适用stringBuffer
对象比较
Comparable
comparable接口实际上是出自java.lang包,它有一个comparaTo(Object obj)方法来排序。
Comparator
comparator接口实际上是出自java.util包它有一个compare(Object obj1, Object obj2)方法来排序
一般我们需要对一个集合使用自定义排序时,我们就要重写compareTo()方法或compare()方法,当我们需要对某一个集合实现两种排序方式,比如一个song对象中的歌名和歌手名分别采用一种排序方法的话,我们可以重写compareTo()方法和使用自制的Comparator方法或者以两个Comparator来实现歌名排序和歌星名排序,第二种代表我们只能使用两个参数版的Collections.sort()