编码与存储单位

  • ASCII:一个字符通常占 1 字节(8 位),只能表示英文、数字和少量符号。
  • UTF-8:变长编码,英文字符占 1 字节,汉字通常占 3 字节(部分生僻字占 4 字节)。
  • 单位换算
    • 1 M = 1024 KB
    • 1 KB = 1024 Byte(字节)
    • 1 Byte = 8 bit(比特)

值传递

Java 中只有值传递,没有引用传递。

  • 基本类型:传递的是值的副本,方法内修改不影响原变量。
  • 引用类型(数组、对象):传递的是引用的副本(即对象地址的拷贝)。方法内可以通过引用修改对象的字段,但重新指向新对象不会影响原引用。
1
2
3
4
public void test(Person p) {
p.setName("new"); // 会影响原对象
p = new Person(); // 不影响原引用
}

Object 类

  • ==:比较两个对象的内存地址是否相同(基本类型比较值)。
  • equals():默认行为同 ==,通常需要重写以实现内容相等判断(如 StringInteger 等)。
  • hashCode():返回对象的哈希值。重写 equals 时必须重写 hashCode,保证两个相等对象哈希值一致。
1
2
3
4
5
@Override
public boolean equals(Object obj) { ... }

@Override
public int hashCode() { ... }

String 类

  • 字符串常量池String s = "abc"; 会先在常量池中查找,存在则复用,否则创建。
  • 堆对象new String("abc") 会在堆中创建新对象,常量池中也会创建(存在就不创建)。
  • **intern()**:返回常量池中的引用。如果常量池中没有,则创建并返回。
1
2
3
4
String a = "abc";
String b = new String("abc");
System.out.println(a == b); // false
System.out.println(a == b.intern()); // true
  • StringBuilder 与 StringBuffer
    • StringBuilder:线程不安全,性能高。
    • StringBuffer:线程安全(方法使用 synchronized),性能稍低。

深浅拷贝

  • 浅拷贝:基本类型和 String 直接复制值,对象类型复制引用(指向同一对象)。默认的 clone() 实现为浅拷贝。
  • 深拷贝:复制对象及其引用的所有子对象。实现方式:
    • 实现 Cloneable 接口并重写 clone() 方法,手动为每个引用类型字段调用 `clone()。(当然你这个clone也要去实现一样,去new对象,不然还是浅拷贝)
    • 使用序列化(Serializable)方式。
    • 使用拷贝构造器或工厂方法。
1
2
3
4
5
6
@Override
protected Object clone() throws CloneNotSupportedException {
DeepCopy dc = (DeepCopy) super.clone();
dc.inner = (Inner) inner.clone(); // 手动深拷贝
return dc;
}

泛型

  • 泛型擦除:编译后泛型类型会被擦除为 Object(或边界类型),运行时无法获取具体类型参数。
  • 好处:编译时类型检查,避免强制类型转换。

泛型类:image-20260523211722144

泛型方法:

image-20260523211821860

通配符

  • 无界通配符 List<?>:表示任意类型,只能读不能写(除 null 外)。

    image-20260523211844003

  • 上界通配符 List<? extends Book>:表示 Book 及其子类。只能读(返回 Book),不能添加元素(除了 null)。

    image-20260523211932203

  • 下界通配符 List<? super Book>:表示 Book 及其父类。可以添加 Book 及其子类,读取时只能获取 Object

    image-20260523212253404

  • 口诀:PECS:produce是extend,consumer是super

    image-20260523212800264


反射

  • 获取 Class 对象的三种方式

    1
    2
    3
    Class<?> clazz1 = Person.class;
    Class<?> clazz2 = Class.forName("com.example.Person");
    Class<?> clazz3 = new Person().getClass();
  • 常用功能:动态创建实例、调用方法、访问字段、获取注解信息。

注解(Annotation)

  • 本质是接口,编译后继承 java.lang.annotation.Annotation
  • 元注解(用于定义注解的注解)
    • @Target:限定注解适用位置(方法、字段、类等)。
    • @Retention:保留策略(SOURCE、CLASS、RUNTIME)。
    • @Documented:是否生成到 Javadoc。
    • @Inherited:是否允许子类继承。
1
2
3
4
5
6
7
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
String value() default "";
int priority() default 0;
String[] tags() default {};
}

BigDecimal

浮点数(float/double)在二进制中无法精确表示某些十进制小数,故使用 BigDecimal 进行精确计算。

  • 构造:推荐使用 String 构造器,避免精度丢失。

    1
    BigDecimal bd = new BigDecimal("0.1");
  • 比较

    • equals():比较数值和精度(2.02.00 不相等)。
    • compareTo():只比较数值(2.02.00 相等)。
1
bd1.compareTo(bd2) == 0   // 数值相等

异常处理

  • Throwable 根类
    • Error:JVM 内部错误(如 OutOfMemoryError),不可恢复,无需捕获。
    • Exception:程序可处理的异常。
      • Checked Exception(编译时异常):必须 throwstry-catch(如 IOException)。
      • Unchecked Exception(运行时异常):不强制处理(如 NullPointerException)。
  • try-with-resources(自动关闭资源)
    • 实现了 AutoCloseable 接口的资源可以在 try 括号中声明,无论是否异常都会自动关闭。
    • 本质是语法糖,编译后生成 finally 块。
1
2
3
4
5
6
try (Scanner scanner = new Scanner(new File("test.txt"))) {
// 使用 scanner
} catch (IOException e) {
// 处理异常
}
// scanner 自动关闭

Lambda 表达式

  • 语法(参数) -> { 方法体 }
  • 本质:不是匿名内部类的语法糖,而是通过 ==invokedynamic 动态生成实现类并复用,性能更高。==
  • 使用前提:目标类型必须是函数式接口(只有一个抽象方法的接口)。
1
2
3
4
5
6
7
8
9
// 匿名内部类
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("hello");
}
};
// Lambda
Runnable r2 = () -> System.out.println("hello");

接口(Interface)

  • Java 8 之前:只能包含常量(public static final)和抽象方法。
  • Java 8 新增
    • 默认方法default):提供默认实现,子类可选择重写。
    • 静态方法static):通过接口名直接调用。
  • Java 9 新增:私有方法(private),用于代码复用。
1
2
3
4
5
6
7
8
9
10
11
public interface MyInterface {
void abstractMethod();

default void defaultMethod() {
System.out.println("default");
}

static void staticMethod() {
System.out.println("static");
}
}

函数式接口

  • 定义:有且仅有一个抽象方法的接口(可以有多个默认/静态方法)。

  • 注解@FunctionalInterface(可选,但推荐使用,编译器会检查)。

  • 四大内置函数式接口

    接口 抽象方法 作用
    Supplier<T> T get() 供给型,无入参,返回结果
    Consumer<T> void accept(T t) 消费型,一个入参,无返回值
    Predicate<T> boolean test(T t) 断定型,判断条件
    Function<T,R> R apply(T t) 函数型,输入 T 输出 R
1
2
// 使用 Lambda 实现函数式接口
Predicate<String> nonEmpty = s -> s != null && !s.isEmpty();

方法引用

  • 作用:Lambda 表达式的语法糖,进一步简化代码。
  • 四种形式
    1. 类名::静态方法Math::max(a,b) -> Math.max(a,b)
    2. 对象::实例方法System.out::printlnx -> System.out.println(x)
    3. 类名::实例方法String::lengths -> s.length()
    4. 构造器引用ArrayList::new() -> new ArrayList<>()
1
2
List<String> list = Arrays.asList("a", "b");
list.forEach(System.out::println); // 方法引用

Stream 流

操作三步骤:创建流 → 中间操作(惰性) → 终端操作(触发计算)。

1. 创建流

1
2
3
4
5
6
7
8
// 集合
Stream<String> stream = list.stream();
// 数组
Stream<Integer> intStream = Arrays.stream(new Integer[]{1,2,3});
// 值
Stream<String> ofStream = Stream.of("a", "b");
// 无限流
Stream.generate(Math::random).limit(5);

2. 中间操作

  • 筛选与切片filterdistinctlimitskip
  • 映射mapflatMap(将每个元素转为另一个流并合并)
  • 排序sortedsorted(Comparator)

3. 终端操作

  • 匹配与查找allMatchanyMatchnoneMatchfindFirstfindAny
  • 规约reduce(求和、拼接等)
  • 收集collect(Collectors.toList())
1
2
3
4
5
List<Integer> evens = list.stream()
.filter(n -> n % 2 == 0)
.map(n -> n * 2)
.sorted()
.collect(Collectors.toList());

并行流

  • 创建collection.parallelStream()stream.parallel()
  • 底层:使用 ForkJoinPool.commonPool()(默认线程数为 CPU 核心数)。
  • 注意事项
    • 线程安全:避免使用非线程安全的集合(如 ArrayList)并行修改,使用 collectConcurrentHashMap
    • 性能:任务拆分成本高,小数据量不建议使用。
1
2
3
list.parallelStream()
.filter(...)
.forEach(...); // 顺序随机

Optional

容器类,代表一个值存在或不存在,用于避免 NullPointerException

  • 创建
    • Optional.of(value):value 不能为 null。
    • Optional.ofNullable(value):允许 null。
    • Optional.empty():空容器。
  • 常用方法
    • isPresent() / isEmpty():判断是否存在。
    • ifPresent(Consumer):有值则执行。
    • map(Function) / flatMap(Function):转换值,返回新 Optional。
    • orElse(T) / orElseGet(Supplier) / orElseThrow():获取值或备选。
1
2
3
4
// 链式调用替代深层 if-null
String city = user.map(User::getAddress)
.map(Address::getCity)
.orElse("Unknown");

最佳实践Optional 主要用作方法返回值,明确告知调用者可能为空;不要用作字段类型或方法参数。