Java核心类

Java官方文档:https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/lang/String.html

 

String

  字符串在String内部是通过一个char[]数组表示的

String s2 = new String(new char[] {'H', 'e', 'l', 'l', 'o', '!'});

  各类函数的使用可参考官方文档

  Stringchar[]类型可以互相转换,方法是:

char[] cs = "Hello".toCharArray(); // String -> char[]
String s = new String(cs); // char[] -> String

 

StringBuilder

  虽然String可以直接拼接字符串。但是,在循环中,每次循环都会创建新的字符串对象,然后扔掉旧的字符串。这样,绝大部分字符串都是临时对象,不但浪费内存,还会影响GC效率。

  StringBuilder,它是一个可变对象,可以预分配缓冲区,这样,往StringBuilder中新增字符时,不会创建新的临时对象

StringBuilder sb = new StringBuilder(1024);
for (int i = 0; i < 1000; i++) {
    sb.append(',');
    sb.append(i);
}
String s = sb.toString();

  并且StringBuilder支持链式操作:

        var sb = new StringBuilder(1024);
        sb.append("Mr ")
          .append("Bob")
          .append("!")
          .insert(0, "Hello, ");

 

  StringBuffer,这是Java早期的一个StringBuilder的线程安全版本,它通过同步来保证多个线程操作StringBuffer也是安全的,但是同步会带来执行速度的下降。

 

包装类

  Java核心库为每种基本类型都提供了对应的包装类型:boolean Boolean; type Type; short Short; int Integer; long Long; float Float; double Double; char Character。

int i = 100;
Integer n = Integer.valueOf(i);
int x = n.intValue();

Integer n = 100; // 编译器自动使用Integer.valueOf(int)
int x = n; // 编译器自动使用Integer.intValue()

Integer n = null;
int i = n;    //报错 基本类型不允许为null

 

  所有的包装类型都是不变类。我们查看Integer的源码可知,它的核心代码如下:

public final class Integer {
    private final int value;
}

 

Enum

  通过枚举定义的类和class定义的类没有任何区别。enum定义的类型就是class,只不过它有以下几个特点:

  • 定义的enum类型总是继承自java.lang.Enum,且无法被继承;
  • 只能定义出enum的实例,而无法通过new操作符创建enum的实例;
  • 定义的每个实例都是引用类型的唯一实例;
  • 可以将enum类型用于switch语句。
enum Weekday {
    SUN, MON, TUE, WED, THU, FRI, SAT;
}

Weekday day = Weekday.SUN;
day == Weekday.SAT || day == Weekday.SUN //true 

  如果枚举包含数字和中文可以如下定义和使用:

public class Main {
    public static void main(String[] args) {
        Weekday day = Weekday.SUN;
        if (day.dayValue == 6 || day.dayValue == 0) {
            System.out.println("Today is " + day + ". Work at home!");
        } else {
            System.out.println("Today is " + day + ". Work at office!");
        }
    }
}

enum Weekday {
    MON(1, "星期一"), TUE(2, "星期二"), WED(3, "星期三"), THU(4, "星期四"), FRI(5, "星期五"), SAT(6, "星期六"), SUN(0, "星期日");

    public final int dayValue;
    private final String chinese;

    private Weekday(int dayValue, String chinese) {
        this.dayValue = dayValue;
        this.chinese = chinese;
    }

    @Override
    public String toString() {
        return this.chinese;
    }
}

 

BigInteger

  表示任意大小的整数。BigInteger内部用一个int[]数组来模拟一个非常大的整数;从Number继承

BigInteger bi = new BigInteger("1234567890");
System.out.println(bi.pow(5)); // 2867971860299718107233761438093672048294900000

  对BigInteger做运算的时候,只能使用实例方法,例如,加法运算:

BigInteger i1 = new BigInteger("1234567890");
BigInteger i2 = new BigInteger("12345678901234567890");
BigInteger sum = i1.add(i2); // 12345678902469135780

 

BigDecimal

  BigInteger类似,BigDecimal可以表示一个任意大小且精度完全准确的浮点数。也是继承至Number

  BigDecimalscale()表示小数位数,例如:

BigDecimal d1 = new BigDecimal("123.45");
System.out.println(d1.scale()); // 2,两位小数

  

  通过BigDecimalstripTrailingZeros()方法,可以将一个BigDecimal格式化为一个相等的,但去掉了末尾0的BigDecimal

BigDecimal d1 = new BigDecimal("123.4500");
BigDecimal d2 = d1.stripTrailingZeros();    //123.45

 

  可以对一个BigDecimal设置它的scale setscale(),如果精度比原始值低,那么按照指定的方法进行四舍五入或者直接截断:

BigDecimal d1 = new BigDecimal("123.456789");
BigDecimal d2 = d1.setScale(4, RoundingMode.HALF_UP); // 四舍五入,123.4568

 

  对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做除法的同时求余数; 调用divideAndRemainder()方法时,返回的数组包含两个BigDecimal,分别是商和余数,其中商总是整数,余数不会大于除数。我们可以利用这个方法判断两个BigDecimal是否是整数倍数:

BigDecimal n = new BigDecimal("12.345");
BigDecimal m = new BigDecimal("0.12");
BigDecimal[] dr = n.divideAndRemainder(m);
System.out.println(dr[0]); // 102
System.out.println(dr[1]); // 0.105

  

  在比较两个BigDecimal的值是否相等时,要特别注意,使用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变为2
System.out.println(d1.compareTo(d2)); // 0

  必须使用compareTo()方法来比较,它根据两个值的大小分别返回负数、正数和0,分别表示小于、大于和等于。

 

  如果查看BigDecimal的源码,可以发现,实际上一个BigDecimal是通过一个BigInteger和一个scale来表示的,即BigInteger表示一个完整的整数,而scale表示小数位数:

public class BigDecimal extends Number implements Comparable<BigDecimal> {
    private final BigInteger intVal;
    private final int scale;
}

 

 

Math

  Math类就是用来进行数学计算的,它提供了大量的静态方法来便于我们实现数学计算

 

Random

  Random用来创建伪随机数。所谓伪随机数,是指只要给定一个初始的种子,产生的随机数序列是完全一样的。

  创建Random实例时,如果不给定种子,就使用系统当前时间戳作为种子,因此每次运行时,种子不同,得到的伪随机数序列就不同

 

SecureRandom

  用来创建安全的随机数,SecureRandom无法指定种子,它使用RNG(random number generator)算法

 

posted @ 2019-11-12 21:31  GodL  阅读(243)  评论(0编辑  收藏  举报