本文是Java的面向对象篇,学习于廖雪峰的Java教程.

Java核心类

1.String

  • String字符串内部是通过一个char[]表示的。
  • String字符串不可变性的实现:通过内部的private final char[]实现。
  • 字符串的比较
    • equals()方法来比较,而不用==
    • Java编译器在编译期间,会把拥有相同字符串的对象视为同一个对象并且放入常量池,所以用==比较字符串得出的结果会有巧合性。
    • 忽略大小写比较字符串用equalsIgnoreCase()方法。
  • 判断是否包含子串用contains()方法,参数为CharSequence类,为String的子类。
  • 搜索字串
    • indexOf()方法返回字串第一次出现在前半部分的索引。
    • lastIndexOf()方法返回子串第一次出现在后半部分的索引。
  • 判断是否以子串开头或结尾
    • startsWith()判断是否以子串开头。
    • endsWith()判断是否以字串结尾。
  • 提取字串
    • substring(2)从索引为2处开始提取字串。
    • substring(2,4)从索引为2处开始提取,到索引为4处结束,但不包括索引为4的值。
  • 去除首尾空白字符
    • trim()方法,空白字符包括\t\r\n
    • strip()方法,与trim方法的区别就是可以去除中文空格字符\u3000
  • 判断是否为空
    • isBlank()方法可以判断是否包含空白字符。
    • isEmpty方法可以判断是否字符串的长度是否为0,空白字符也可作为一个字符串长度。
  • 替换子串用replace(s1,s2)方法,其中第一个参数s1表示被替换的子串,第二个参数s2为替换的子串。
  • spilt()方法可以分割字符串。
  • 格式化字符串
    • formatted()
    • format()静态方法
    • 示例代码
public class Main {
    public static void main(String[] args) {
        String s = "Hi %s, your score is %d!";
        System.out.println(s.formatted("Alice", 80));
        System.out.println(String.format("Hi %s, your score is %.2f!", "Bob", 59.5));
    }
}
  • 类型转换
    • 基本数据类型或引用类型转String类型。
      • 使用String.valueOf()静态方法。
      • 使用toString()静态方法。
    • String类型转其他类型:
      • 转int:Integer.parseInt()Integer.valueOf()方法。
      • 转bolean:Bolean.parseBolean()Boolean.valueOf()方法。
      • ···
  • char[ ]和String的相互转换
    • String转char[ ]:char[] arr = s.toCharArray()toCharArray()方法。
    • char[ ]转String:String s =new String (arr)

2.StringBuilder

  • 在循环中使用 + 拼接字符串会生成许多临时对象,这些会造成内存浪费,同时会影响GC效率,StringBuilder可以有效解决这个问题。
  • StringBuilder是一种可变类,可以预分配缓冲区。
  • StringBuilder使用append()方法拼接子串。
  • StringBuilder使用delete()方法删除子串。
  • StringBufferStringBuilder的线程安全版本,实现了相同的接口。
  • 可以通过同步来保证线程操作,但同步会带来执行速度的下降。

3.StringJoiner

  • Stringjoiner类最常用于用分隔符拼接数组,使用add()方法拼接。
  • 用法:var sj = new StringJoiner("s1"),其中参数s1为分隔符。
String[] names = {"Bob", "Alice", "Grace"};
var sj = new StringJoiner(", ");
for (String name : names) {
    sj.add(name);
}
  • 如果要指定开头和结尾,var sj = new StringJoiner("s1","s2","s3"),其中参数s1为分隔符,s2为开头,s3为结尾。

    String[] names = {"Bob", "Alice", "Grace"};
    var sj = new StringJoiner(", ", "Hello ", "!");
    for (String name : names) {
        sj.add(name);
    }
  • String.join()为String类的静态方法,内部使用了StringJonier类的方法来拼接子串。

  • String.join()方法的使用:s.join("s",arr),其中s为要拼接的子串,arr为字符串数组。

4.包装类型

  • 基本数据类型变为引用类型,其实是使引用类型包含一个基本类型的字段。
  • 包装类:与某种基本类型对应的引用类型称为包装类(Wrapper Class)。
  • 需要注意两种引用类型IntegerCharacter,其他基本与基本类型的名称一致。
  • 推荐使用包装类型的静态方法valueOf()创建实例,而不通过构造方法创建,因为会有编译警告。
  • 自动装箱(Auto Boxing):将基本类型自动转换为引用类型。
  • 自动拆箱(Auto Unboxing):将引用类型自动转换为基本类型。
  • 自动装箱和自动拆箱只发生在编译阶段,优点是少写代码,缺点是影响执行效率。
  • 静态工厂方法:能创建新实例的静态方法,它有缓存优化机制。
  • 如果静态工厂方法valueOf()中的参数很小,会返回相同的实例,由于缓存优化。
  • 包装类型转化为基本类型
    • 使用形如intvalue()的方法、
    • 使用形如parseInt()的方法。
  • 包装类型的静态变量
Boolean t = Boolean.TRUE;
Boolean f = Boolean.FALSE;
// int可表示的最大/最小值:
int max = Integer.MAX_VALUE; // 2147483647
int min = Integer.MIN_VALUE; // -2147483648
// long类型占用的bit和byte数量:
int sizeOfLong = Long.SIZE; // 64 (bits)
int bytesOfLong = Long.BYTES; // 8 (bytes)

5.JavaBean

  • JavaBean主要用来传递数据,即把一组数据组合成一个JavaBean便于传输。
  • 一组对应的读写方法称为属性。
  • 只有读方法的称为只读属性,只有写方法的称为只写属性。

6.Enum

  • enum关键字定义的类称为枚举类,它被编译器编译为final class Xxx extends Enum { … }
  • 注意:
    • 枚举常量带有类型信息。
    • 不能用非枚举类型的值给枚举常量赋值。
    • 不同类型的枚举不能相互比较。
  • 枚举的比较
    • == 运算符,枚举类是一种特殊的class,可以用==运算符比较,因为每一个枚举常量在JVM内都是一个唯一的实例。
    • equals()方法,可编译通过,但更推荐用==运算符,可以写更少的代码。
  • 枚举类的特点
    • 继承自java.lang.Enum,且枚举类无法被继承,因为枚举类被fintal关键字修饰。
    • 只能定义enum的实例,不能用new操作符创建实例。
    • 可以用于switch语句。
    • 每一个枚举常量在内部都是一个唯一的实例。
  • name()返回枚举常量名。
  • ordinal()返回枚举常量按顺序定义的序号,以0开始计数。
  • enum的构造方法应该声明为private类型
  • 给枚举常量添加字段,字段强烈建议声明为final类型,并且在pirvate构造方法中初始化。
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;
    }

7.Record

  • 不变类的两个特点
    • classfinal关键字修饰。
    • 字段也用final关键字修饰。
  • 用关键字record声明的类称为记录类。
  • 跟枚举类一样,它不直接继承自Record类,而由编译器实现继承,并且被编译器编译为public final class Xxx extends Record {···}
  • 记录类的声明方式
public record Xxx(type x,type y);

它被编译器编译后的代码为:

public final class Point extends Record {
    private final type x;
    private final type y;

    public Point(type x, type y) {
        this.x = x;
        this.y = y;
    }

    public type x() {
        return this.x;
    }

    public type y() {
        return this.y;
    }

    public String toString() {
        return String.format("Point[x=%s, y=%s]", x, y);
    }

    public boolean equals(Object o) {
        ...
    }
    public int hashCode() {
        ...
    }
}
  • 可以在记录类的构造方法中编写逻辑检查语法。
  • 可以在记录类中用of()静态方法创建实例。

8.BigInteger

  • 由CPU原生提供的long整型最大位数是64位,可直接通过CPU进行计算。
  • java.math.BigInteger表示任意大小的整数,内部以int[ ]数组表示。
  • 使用BigInteger做运算的时候,要用实例方法。
  • BigIntegerlong时,如果超出long范围,用longValneExact()方法会报出ArithmeticException异常,用longValne()方法不会报出异常,但会丢失高位信息,即得出的结果不准确。
  • BigInteger类型也可转基本类型,因为BigInteger也继承自Number类。

9.BigDecimal

  • BigDecimal表示任意精度的浮点数。
  • 使用scale()方法可以返回小数位数,如果返回负数,表示这是整数,并且末尾有整数0。
  • 使用stripTrailingZeros()方法可以返回一个相等的,去除了末尾0的BigDecimal数。
  • 使用setScale()方法可以设置精度,如果设置精度小与原始精度,就要考虑四舍五入或者直接截断。
  • RoundingMode.HALF_UP常量表示四舍五入。
  • RoundingMode.Down常量表示直接截断。
  • 比较两个BigDecimal使用compareTo()方法。
  • BigDecimal实际上是由BigIntegersacle表示的。

10.Math

  • 数学公式
    • Math.abs()计算绝对值。
    • Math.max()计算最大值,min()计算最小值
    • Math.pow(x,y)计算$x^y$次方。
    • Math.sqrt(x)计算$\sqrt{x}$。
    • Math.exp(x)计算$e^x$。
    • Math.log(x)计算$\log_ex$。
    • Math.log10(x)计算$\ln x$。
    • Math.sin(x)计算$\sin x$。
    • Math.cos(x)计算$\cos x$。
    • Math.tan(x)计算$\tan x$。
    • Math.asin(x)计算$asin x$。
    • Math.acos(x)计算$acos x$。
    • Math.PI数学常量,表示$\Pi$
    • Math.E数学常量,表示e。
  • Math.random()返回[0,1之间的随机数。

11.Random

  • Random类用来创建伪随机数,伪随机数是指给定一个种子,会产生相同的随机数序列。
  • Math.random()实际上内部调用了Random类。
  • SecureRandom类用来产生安全的随机数。