Skip to content

链式调用底层

实现链式调用的方式就是每个可以链式调用的方法返回了自身的 this 实例,进而可以链式访问方法。

java
public class Main {
    public static void main(String[] args) {
        Adder adder = new Adder();
        adder.add(3)
             .add(5)
             .inc()
             .add(10);
        System.out.println(adder.value());
    }
}

class Adder {
    private int sum = 0;

    public Adder add(int n) {
        sum += n;
        return this;
    }

    public Adder inc() {
        sum ++;
        return this;
    }

    public int value() {
        return sum;
    }
}

包装

底层是:

java
public final class Integer {
    private final int value;
}

因此对象创建后其属性具有不变性。 使用 Integer n = Integer.valueOf(100)(静态工厂方法)来让该类去管理对象的创建,而不是每次手动去 new 对象,得不到 JDK 的优化。 包装类型是引用类型(引用类型可以赋值为 null,基本类型不行) 深入理解为什么"所有的整数和浮点数的包装类型都继承自 Number,因此,可以非常方便地直接通过包装类型获取各种基本类型"Number 类是 Java 平台中所有表示数值的类的抽象基类,它定义了一些通用的方法,并且强制要求子类实现。 因此各子类既然是继承自该类的,自然可以实现相应的转换,调用声明的方法。 在一些地方不用显示转换,编译器会自己进行自动装箱和自动拆箱。

JavaBean

一个类中属性的读取满足:

java
// 读方法:
public Type getXyz()
// 写方法:
public void setXyz(Type value)

符合这种条件的 class 被称为JavaBean

内省器

内省(Introspection)在计算机科学和编程语言中,通常指的是一个程序在运行时获取关于自身的类型信息、属性、方法等结构的能力。这种能力允许程序动态地检查和操作对象的状态和行为,而无需在编译时知道这些信息。 比如枚举一个类下的所有 bean:

java
import java.beans.*;

public class Main {
    public static void main(String[] args) throws Exception {
        BeanInfo info = Introspector.getBeanInfo(Person.class);
        for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
            System.out.println(pd.getName());
            System.out.println("  " + pd.getReadMethod());
            System.out.println("  " + pd.getWriteMethod());
        }
    }
}

枚举类

enum 是引用类型,作为常量,因此拥有唯一实例。 可以通过构造方法为枚举类成员增加属性:

java
enum Weekday {
    MON(1), TUE(2), WED(3), THU(4), FRI(5), SAT(6), SUN(0);

    public final int dayValue; // 常量字段

    private Weekday(int dayValue) { // 私有构造
        this.dayValue = dayValue;
    }
}

也可以用在 switch 中。

记录类

不变类

一个不变类具有以下特点:

  1. 定义class时使用final,无法派生子类;
  2. 每个字段使用final,保证创建实例后无法修改任何字段。
java
public final class Point {
    private final int x;
    private final int y;

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

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

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

此外,还需要正确覆写 equals()hashCode()。 为了简化这个过程,可以使用 record 来创建一个记录类:

java
// Record
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);
    }
}

record Point(int x, int y) {}

自动为我们创建了构造方法,和字段名同名的方法,以及覆写 toString()equals()hashCode() 方法。 可以直接在构造函数中添加检查逻辑,但不要写明赋值语句,编译器会加上,称之为Compact Constructor(简约构造器)