StringBuilder
StringBuilder是可变对象,可以预分配缓冲区,新增字符时,不会创建新的临时对象。解决了String拼接字符串会浪费内存,影响GC效率的问题。
StringBuilder可以进行链式操作,查看源码可知,进行链式操作的关键是定义的append()方法会返回this,这样就可以不断调用自身的其他方法。
如:
class Adder {
private int sum = 0;
public Adder add(int n) {
sum += n;
return this;
}
}
例:
StringBuilder sb = new StringBuilder(1024);
for (int i = 0; i < 1000; i++) {
sb.append(',');
sb.append(i);
}
String s = sb.toString();
StringBuffer
StringBuffer是java早期的一个StringBuilder的线程安全版本,允许多个线程操作,但是执行速度较慢。StringBuilder和StringBuffer接口完全相同,现在完全没有必要使用StringBuffer。
StringJoiner
StringJoiner可以在拼接时,指定间隔符,开头和结尾。
例:
StringJoiner sj = new StringJoiner(", ", "Hello ", "!");
String.join()
String.join()内部就是调用了StringJoiner来拼接字符串,
例:
String s=String.join(",",names);
引用类型
创建引用类型有两种方法:
以Integer为例:
1、Integer n=new Integer(100);
2、Integer n=Integer.valueOf(100);
方法1:每次都会创建新的实例。
方法2:把内部优化留给实例的实现者去做。
创建“新”对象的静态方法称为静态工厂方法,Integer.valueOf()就是静态工厂方法,它会尽可能地返回缓存的实例以节省内存。
创建新对象时,应优先选用静态工厂方法。
引用类型必须使用equals()进行比较,== 是比较两个应用类型的变量是否是同一个对象。
但是enum类型可以使用==进行比较,因为enum类型的每个常量在JVM中只有一个唯一实例。
枚举类 enum
enum定义的类就是class,区别
1、继承自java.lang.Enum,但他不能被继承。
2、只能定义出enum实例,无法通过new操作符创建
3、定义的每个实例都是 引用类型 的 唯一实例
4、可以将enum类型用于switch语句
enum构造方法使用private,字段强烈建议使用final.
不变类
不变类的定义:
1、定义class时使用final,无法派生子类。
2、每个字段使用final,保证创建实例后无法修改任何字段。
java14后,可以使用record来定义不变类。它可以帮我们用final修饰class以及每个字段,还自动为我们创建构造方法,和字段名同名的方法,以及覆写toString()、equals()和hashCode()方法。
如:
public class Main {
public static void main(String[] args) {
Point p = new Point(123, 456);
System.out.println(p.x());
System.out.println(p.y());
System.out.println(p);
}
}
public record Point(int x, int y) {}//不变类
瑕疵:record创建的不变类中构造函数无法为我们检查参数(如某些参数不允许为负数),我们需要手动在构造函数中添加判断程序`
所有包装类型都是不变类,即里面的变量都是不可变的。
如:
public final class Integer {
private final int value;
}
引用类型进行比较都应该用equal(),而不是**==**。
因为编译器为了节省内存,如Integer.valueOf()会对较小的数返回相同的实例(<=127),所以较小的数用==比较结果为true,较大则为false。
但为了安全起见,我们应该用equal()去比较两个引用类型。
BigInteger和BigDemical
超过64位long型整数需要使用BigInteger来表示,其内部用一个int[]数组来模拟一个非常大的整数。
BigInteger计算只能使用实例方法,如:
BigInteger bi1=new BigInteger("123");
BigInteger bi2= new BigInteger("1234567890");
BigInteger bi=bi1.add(bi2);
结果:1234568013
优缺点:
和long型比较整数运算比,BigInteger不会有范围限制,但缺点是速度比较慢。
BigInteger和Integer、Long一样都是继承Number类,也是不变类。
转换为其他类型时,最好使用xxxValueExact()进行转换,避免超出范围丢失高位信息。若只用xxxValue会返回Infinity(无限)。
BigDecimal和BigInteger类似,BigDecimal可以表示一个任意大小且精度完全准确的浮点数。它也是不可变对象,继承自Number。
如:
BigDecimal d1 = new BigDecimal("123.45");
BigDecimal d2 = new BigDecimal("123.4500");
BigDecimal d3 = new BigDecimal("1234500");
System.out.println(d1.scale()); // 2,两位小数
System.out.println(d2.scale()); // 4
System.out.println(d3.scale()); // 0
可以通过scale()表示小数位数,stripTrailingZeros()可以将一个BigDecimal格式化为一个相等的,但去掉了末尾的0,整数也可以这么用。
若scale()返回的是负数(一般该数是被stripTrailingZeros()处理过了),如-2,则代表该数为整数,且末尾有两个0。
可以设置一个BigDecimal的scale,能够指定使用四舍五入还是直接截断。
BigDecimal做乘、减、加时,精度不会丢失,但是做除法时,存在无法除尽的情况,这时就必须指定精度以及如何进行截断。
BigDecimal d1 = new BigDecimal("123.456");
BigDecimal d2 = new BigDecimal("23.456789");
BigDecimal d3 = d1.divide(d2, 10, RoundingMode.HALF_UP); // 保留10位小数并四舍五入
BigDecimal d4 = d1.divide(d2); // 报错:ArithmeticException,因为除不尽
两个BigDecimal的值是否相等,若使用equals()进行比较,必须两个数的scale()相同才会相等 如:123.45和123.4500是不相等的
所以最好用compareTo()来比较,它会根据两个值的大小分别返回负数、正数、0,分别代表小于、大于、等于。
实际上BigDemical是通过一个BigInteger和一个scale()进行表示的。
java核心库中的常用工具类
Math类,提供大量的静态方法来便于我们实现数学计算。
求绝对值
StrictMath保证所有平台计算结果都是完全相同的
Random生成伪随机数,
SecureRandom生成安全的随机数,无法破解。
学习自:
添加链接描述