【Java】Java 基础系统学习笔记

Java 基础系统学习笔记

本笔记结合课件图片与实际代码,覆盖 Java 基础到高级的核心知识点,所有代码示例均采用英文命名规范。


Java 基础

Hello World

每个 Java 程序的起点都是 public static void main(String[] args)

java 复制代码
package com.anti.test;

import java.util.Scanner;

public class HelloWorld {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int a = sc.nextInt();
        int b = sc.nextInt();
        System.out.println(a + b);
    }
}

命名规范

Java 遵循两种命名规范:

  • 小驼峰 (方法和变量):nameappleCountfirstName
  • 大驼峰 / PascalCase (类名):StudentHelloWorldSnakeGame

标识符规则

  • 由字母、数字、下划线 _、美元符 $ 组成
  • 不能以数字开头
  • 不能是关键字
  • 区分大小写

基本数据类型

类型 大小 范围
byte 1 字节 -128 到 127
short 2 字节 -32768 到 32767
int 4 字节 -2^31 到 2^31-1
long 8 字节 -2^63 到 2^63-1
float 4 字节 约 6-7 位小数
double 8 字节 约 15 位小数
char 2 字节 0 到 65535
boolean 1 位 true / false

类型转换

  • 隐式转换 :小类型 → 大类型(如 intlongfloatdouble
  • 显式转换 :大类型 → 小类型(如 (int) 3.14
  • byteshortchar 参与运算时会先提升为 int

字面量类型

整数、小数、字符串(双引号)、字符(单引号)、布尔值(true/false)、空值(null)。


流程控制

if-else 语句

java 复制代码
if (condition) {
    // 条件为真时执行
} else if (anotherCondition) {
    // 另一个条件为真时执行
} else {
    // 所有条件都为假时执行
}

注意事项:

  1. 大括号写在行尾,不另起一行
  2. 如果语句体只有一行,可以省略大括号
  3. 条件括号后不要加分号
  4. 布尔变量直接写变量名:if (flag) 而非 if (flag == true)

switch 语句

java 复制代码
switch (expression) {
    case value1:
        // code
        break;
    case value2:
        // code
        break;
    default:
        // code
}

switch 支持 byteshortintcharStringenum 类型。JDK 12/14 新增了箭头标签、多 case 值和 yield 关键字。

循环

java 复制代码
// for 循环
for (int i = 0; i < 100; i++) {
    // 循环体
}

// while 循环
while (condition) {
    // 循环体
}

// do-while 循环(至少执行一次)
do {
    // 循环体
} while (condition);

break 和 continue

  • break:终止当前循环或 switch
  • continue:跳过当前迭代,继续下一次循环
java 复制代码
// break: i == 3 时停止
for (int i = 1; i <= 5; i++) {
    if (i == 3) { break; }
    System.out.println(i); // 输出 1, 2
}

// continue: 跳过 i == 3
for (int i = 1; i <= 5; i++) {
    if (i == 3) { continue; }
    System.out.println(i); // 输出 1, 2, 4, 5
}

数组

数组定义与遍历

java 复制代码
package com.anti.test.arr1;

public class ArrayDemo {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

System.arraycopy

Java 提供 System.arraycopy() 用于高效数组复制:

java 复制代码
System.arraycopy(src, srcPos, dest, destPos, length);

Arrays 工具类

方法 说明
toString(arr) 将数组转为字符串
binarySearch(arr, key) 二分查找
copyOf(arr, newLength) 复制数组
copyOfRange(arr, from, to) 范围复制
fill(arr, value) 填充数组
sort(arr) 排序

方法与可变参数

可变参数(VarArgs)

可变参数允许方法接收零个或多个同类型参数,语法为 Type... args

java 复制代码
package com.anti.map;

public class VarArgs {
    public static void main(String[] args) {
        System.out.println(sum(1, 2, 3, 4, 5)); // Output: 15
    }

    private static int sum(int... args) {
        int sum = 0;
        for (int i : args) {
            sum += i;
        }
        return sum;
    }
}

要点:

  • 可变参数必须是方法的最后一个参数
  • 底层本质是数组
  • 一个方法最多只能有一个可变参数

面向对象:类与对象

类的定义与封装

java 复制代码
package com.anti.test.classtest;

public class Student {
    private int age;
    private String name;
    private char gender;

    public Student() {
        System.out.println("no-arg constructor");
    }

    public Student(int age, String name, char gender) {
        this.age = age;
        this.name = name;
        this.gender = gender;
    }

    public void show() {
        System.out.println("age:" + age + " name:" + name + " gender:" + gender);
    }

    public void setAge(int age) { this.age = age; }
    public int getAge() { return age; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}

使用类

java 复制代码
package com.anti.test.classtest;

public class StudentDemo {
    public static void main(String[] args) {
        Student s = new Student(18, "Zhang San", 'M');
        s.show();
        s.setAge(19);
        s.show();
        System.out.println(s.getAge());
    }
}

this 关键字

  • 区分成员变量和局部变量(Java 的"就近原则")
  • 调用其他构造方法:this(args)
  • 访问成员变量:this.variableName

权限修饰符

实际开发中,成员变量用 private,方法用 public,从公共代码中提取的辅助方法也用 private


字符串 API

StringBuilder

方法 说明
append(any type) 追加数据,返回对象本身
reverse() 反转内容
length() 返回长度
toString() 转为 String

StringJoiner

方法 说明
add(String) 添加内容,返回对象本身
length() 返回长度
toString() 返回拼接后的字符串
java 复制代码
StringJoiner sj = new StringJoiner(", ", "[", "]");
sj.add("a").add("b").add("c");
System.out.println(sj.toString()); // [a, b, c]

String / StringBuilder / StringJoiner 对比

  • String:不可变字符串
  • StringBuilder:高效拼接可变字符串
  • StringJoiner(JDK 8+):带分隔符的拼接

常用工具 API

Math 类

所有方法均为静态方法。常用:absceilfloormaxminpowsqrtcbrtroundrandom

Runtime 类

java 复制代码
package com.anti.test2.runtime;

public class Test {
    public static void main(String[] args) {
        System.out.println(Runtime.getRuntime().freeMemory() / 1024 / 1024);
        System.out.println(Runtime.getRuntime().totalMemory() / 1024 / 1024);
        System.out.println(Runtime.getRuntime().maxMemory() / 1024 / 1024);
    }
}

System 类

常用方法:currentTimeMillis()arraycopy()exit(status)getProperty(key)

Object 类

Object 是所有类的顶层父类:

  • toString():返回对象的字符串表示
  • equals():比较对象是否相等
  • clone():浅拷贝

继承

基本继承

java 复制代码
package com.anti.test.inheritance;

public class Animal {
    public void eat() { System.out.println("eat"); }
    public void water() { System.out.println("drink water"); }
}

class Cat extends Animal {
    public void catchMouse() { System.out.println("catching mouse"); }
}

class Dog extends Animal {
    public void guardHouse() { System.out.println("guarding house"); }
}

class Husky extends Dog {
    public void demolishHouse() { System.out.println("demolishing house"); }
}

继承中的构造方法

  • 子类不能继承父类的构造方法,但可以通过 super() 调用
  • 子类构造方法首行默认有 super() 调用
  • 父类无参构造先执行,然后子类构造方法执行
  • 调用父类有参构造需显式写 super(args)

继承中的变量访问

遵循就近原则:局部变量 → 本类成员变量 → 父类成员变量。使用 this.namesuper.name 区分。

JavaBean 继承模式

java 复制代码
package com.anti.test.inheritance;

public class EmployeeDemo {
    public static void main(String[] args) {
        Manager m = new Manager();
        m.work();
        m.eat();

        Cook c = new Cook();
        c.work();
        c.eat();
    }
}

class Employee {
    int id;
    String name;
    double salary;
    private char category;

    public void setCategory(char category) { this.category = category; }

    public void work() {
        if (category == 'A') {
            System.out.println("manager is working");
        } else {
            System.out.println("cook is working");
        }
    }

    public void eat() { System.out.println("eating"); }
}

class Manager extends Employee {
    public Manager() { this.setCategory('A'); }
    double bonus;
}

class Cook extends Employee {}

继承规则

  • Java 只支持单继承,但支持多层继承
  • 所有类的顶层父类是 Object

多态

多态成员访问规则

  • 变量:编译看左边,运行也看左边
  • 方法:编译看左边,运行看右边(动态分派)

多态示例

java 复制代码
package com.anti.test.polymorphism;

public class Animal {
    int age;
    String color;

    Animal() { System.out.println("no-arg constructor"); }

    Animal(int age, String color) {
        this.age = age;
        this.color = color;
    }

    public void eat(String something) {
        System.out.println("eating " + something);
    }
}

public class Dog extends Animal {
    Dog() { super(); }
    Dog(int age, String color) { super(age, color); }

    @Override
    public void eat(String something) {
        System.out.println("puppy is eating " + something);
    }

    public void guardHouse() { System.out.println("puppy guarding house"); }
}

public class Cat extends Animal {
    Cat() { super(); }

    @Override
    public void eat(String something) {
        System.out.println("kitten is eating " + something);
    }

    public void catchMouse() { System.out.println("kitten catching mice"); }
}

instanceof 模式匹配

java 复制代码
package com.anti.test.polymorphism;

import java.io.Serializable;

public class Person implements Serializable {
    String name;
    int age;

    public Person(String name, int age) {
        this.age = age;
        this.name = name;
    }

    public void keepPet(Animal a, String something) {
        if (a instanceof Dog d) {
            d.eat(something);
        } else if (a instanceof Cat c) {
            c.eat(something);
        } else {
            System.out.println("no such animal");
        }
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + '}';
    }
}

Person 实现了 Serializable 接口,便于后续对象序列化(见第 22.5 节)。


抽象类

定义

抽象类不能实例化,可以包含抽象方法(无方法体)和具体方法。

java 复制代码
package com.anti.test.abstractclass;

public abstract class Animal {
    String name;
    int age;

    public void drink() {
        System.out.println("drinking water");
    }

    public abstract void eat();
}

具体子类

java 复制代码
public class Dog extends Animal {
    @Override
    public void eat() { System.out.println("eating bones"); }
}

public class Frog extends Animal {
    @Override
    public void eat() { System.out.println("eating bugs"); }
}

public class Sheep extends Animal {
    @Override
    public void eat() { System.out.println("eating grass"); }
}

抽象类注意事项

  • 不能实例化
  • 可以没有抽象方法
  • 可以有构造方法
  • 子类必须重写所有抽象方法,否则子类也要声明为抽象类

接口

接口的演进

  • JDK 7:只有抽象方法
  • JDK 8:新增默认方法和静态方法(有方法体)
  • JDK 9:新增私有方法

接口定义与实现

java 复制代码
package com.anti.test.interface;

public abstract class Animal {
    private String name;
    private int age;

    public Animal() {}
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void show() {
        System.out.println("name:" + name + " age:" + age);
    }

    public abstract void eat();
}

public interface Swim {
    public void swim();
}

public class Dog extends Animal implements Swim {
    public Dog() {}
    public Dog(String name, int age) { super(name, age); }

    @Override
    public void eat() { System.out.println("eating bones"); }

    @Override
    public void swim() { System.out.println("dog paddle"); }
}

public class Frog extends Animal implements Swim {
    public Frog() {}
    public Frog(String name, int age) { super(name, age); }

    @Override
    public void eat() { System.out.println("eating bugs"); }

    @Override
    public void swim() { System.out.println("breaststroke"); }
}

public class Rabbit extends Animal {
    public Rabbit() {}
    public Rabbit(String name, int age) { super(name, age); }

    @Override
    public void eat() { System.out.println("rabbit eating carrots"); }
}

接口成员特点

  • 变量都是常量(public static final
  • 没有构造方法
  • 方法默认是 public abstract

适配器模式

当接口方法很多但只需要一个时,可以创建一个适配器类做空实现,然后继承适配器类只重写需要的方法。


内部类

分类

  1. 成员内部类:在外部类的成员位置定义
  2. 静态内部类 :用 static 修饰的成员内部类
  3. 局部内部类:在方法内定义
  4. 匿名内部类:没有名字的局部内部类

静态内部类

java 复制代码
// 直接创建
Outer.Inner oi = new Outer.Inner();

// 非静态方法:先创建对象,再调用
// 静态方法:Outer.Inner.methodName()

匿名内部类

常用于作为方法参数或实现函数式接口:

java 复制代码
new InterfaceName() {
    @Override
    public void method() {
        // implementation
    }
};

内部类总结

  • 成员内部类被 private 修饰时:在外部类编写方法对外提供内部类对象
  • 成员内部类非 private 修饰时:Outer.Inner oi = new Outer().new Inner();
  • 外部类和内部类变量重名时:Outer.this.variableName 访问外部类变量

代码块

类型 位置 作用
局部代码块 方法内 限定变量作用域(已过时)
构造代码块 类中 提取构造方法共性代码
静态代码块 类中加 static 数据初始化(重要)

静态代码块在类加载时执行一次,优先于任何构造方法。


final 关键字

  • final 类 :不能被继承(如 String
  • final 方法:不能被重写
  • final 变量:只能赋值一次(常量)
  • final 引用:引用不可变,但对象字段可变

异常处理

异常类型

  • 编译时异常 :除 RuntimeException 及其子类外的所有异常,编译时必须处理
  • 运行时异常RuntimeException 及其子类,编译时不检查,通常由参数错误导致

自定义异常

java 复制代码
package com.anti.exception;

public class CustomException extends RuntimeException {
    public CustomException() { super(); }
    public CustomException(String message) { super(message); }
}

try-catch 使用

java 复制代码
package com.anti.exception;

public class Test {
    public static void main(String[] args) {
        try {
            test();
        } catch (CustomException e) {
            e.printStackTrace();
        }
    }

    public static void test() {
        try {
            int[] a = {};
            int i = a[1];
        } catch (Exception e) {
            throw new CustomException("index out of bounds");
        }
    }
}

异常处理总结

  • JVM 默认处理:打印异常名称、原因、位置并退出
  • try-catch:捕获异常并处理
  • throw/throws:抛出异常

集合框架

Collection 体系

复制代码
Collection
  |-- List(有序,可重复)
  |     |-- ArrayList
  |     |-- LinkedList
  |     |-- Vector
  |-- Set(不可重复)
        |-- HashSet
        |     |-- LinkedHashSet
        |-- TreeSet

Map 体系

复制代码
Map(键值对)
  |-- HashMap
  |     |-- LinkedHashMap
  |-- TreeMap

List 遍历的 5 种方式

  1. 迭代器(Iterator)
  2. 列表迭代器(ListIterator)
  3. 增强 for 循环
  4. Lambda 表达式
  5. 普通 for 循环(List 有索引)

TreeMap 示例:字符频率统计

java 复制代码
package com.anti.map;

import java.util.TreeMap;

public class Test {
    public static void main(String[] args) {
        String s = "helloworldmississippithequickbrownfoxjumpsoverthelazydog";
        TreeMap<Character, Integer> map = new TreeMap<>();

        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (map.containsKey(c)) {
                int count = map.get(c);
                count++;
                map.put(c, count);
            } else {
                map.put(c, 1);
            }
        }

        StringBuilder sb = new StringBuilder();
        map.forEach((k, v) -> {
            sb.append(k).append("(").append(v).append(")");
        });
        System.out.println(sb);
    }
}

HashSet 底层原理

HashSet 底层是 HashMap:

  1. 计算元素的哈希值
  2. 如果桶为空,直接添加
  3. 如果不为空,用 equals() 比较:
    • 相同:重复,不添加
    • 不同:添加到链表(链表长度 >= 8 时转红黑树)

参数:初始数组长度 16,负载因子 0.75。

不可变集合

使用 List.of()Set.of()Map.of() 创建:

  • List:直接使用
  • Set:元素不能重复
  • Map :键值对不能重复,最多 10 对。超过 10 对用 Map.ofEntries()

ArrayList 底层实现

创建长度为 0 的数组,首次添加元素时扩容为 10,满了后按 1.5 倍增长。


泛型

泛型类

java 复制代码
class MyGeneric<T> {
    private T value;
    public T getValue() { return value; }
    public void setValue(T value) { this.value = value; }
}

泛型方法

java 复制代码
public <T> void printArray(T[] array) {
    for (T item : array) { System.out.println(item); }
}

通配符

  • <?>:无界通配符,接受任何类型
  • <? extends T>:上界,T 及其子类
  • <? super T>:下界,T 及其父类

要点:

  • 泛型只能使用引用类型
  • 运行时类型擦除
  • 泛型不参与继承

数据结构

常见数据结构

数据结构 特点
先进后出(LIFO)
队列 先进先出(FIFO)
数组 查询快、增删慢(内存连续)
链表 查询慢、增删快(内存不连续)

二叉树

每个节点最多两个子节点:

复制代码
       9
    7     2
  3   8    1
4  6  5  10

二叉搜索树(BST)

左小右大,相同值不存:

复制代码
     7
  4     10
2  5   11
1 3  6  12

遍历方式:

  • 前序遍历:根 → 左 → 右
  • 中序遍历:左 → 根 → 右(BST 中序遍历结果有序)
  • 后序遍历:左 → 右 → 根

平衡二叉树

任何节点的左右子树高度差不超过 1。旋转情况:

  • 左左:右旋
  • 左右:先左旋再右旋
  • 右右:左旋
  • 右左:先右旋再左旋

红黑树

自平衡二叉搜索树,规则:

  1. 每个节点是红色或黑色
  2. 根节点是黑色
  3. 每个叶子节点(NIL)是黑色
  4. 红色节点的子节点必须是黑色
  5. 从任一节点到其叶子的所有路径包含相同数量的黑色节点

Lambda 表达式与方法引用

Lambda 表达式

简化函数式接口(只有一个抽象方法)的写法:

java 复制代码
// 匿名内部类
Arrays.sort(arr, new Comparator<String>() {
    public int compare(String o1, String o2) {
        return o1.length() - o2.length();
    }
});

// Lambda 表达式
Arrays.sort(arr, (o1, o2) -> o1.length() - o2.length());

实际示例

java 复制代码
package com.anti.date;

import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        String[] arr = {"a", "aaa", "aa", "aaaa"};
        Arrays.sort(arr, (o1, o2) -> o1.length() - o2.length());
        System.out.println(Arrays.toString(arr)); // [a, aa, aaa, aaaa]
    }
}

方法引用

java 复制代码
// Lambda:     s -> System.out.println(s)
// Method ref: System.out::println

// Lambda:     (s1, s2) -> s1.equals(s2)
// Method ref: String::equals

方法引用五种类型:静态方法引用、成员方法引用、构造方法引用、类名成员方法引用、数组构造方法引用。


Stream API

概述

Stream API + Lambda 简化集合/数组操作。

步骤:

  1. 获取 Stream 对象
  2. 使用中间方法处理数据
  3. 使用终结方法产出结果

获取 Stream

  • 单列集合collection.stream()
  • 双列集合:先转 entrySet
  • 数组Arrays.stream(array)
  • 零散数据Stream.of(items...)

常用方法

分类 方法
中间方法 filterlimitskipdistinctconcatmap
终结方法 forEachcounttoArraycollect
java 复制代码
list.stream()
    .filter(s -> s.startsWith("a"))
    .map(String::toUpperCase)
    .forEach(System.out::println);

注意:Stream 的修改不会影响原始集合。


日期时间 API

JDK 8+ 时间 API

复制代码
JDK8 Time
  |-- Date class
  |     |-- ZoneId: 时区
  |     |-- Instant: 时间戳
  |     |-- ZonedDateTime: 带时区的时间
  |-- Calendar class
  |     |-- Calendar
  |     |-- LocalDate: 年月日
  |     |-- LocalTime: 时分秒
  |     |-- LocalDateTime: 以上全部
  |-- Formatting
  |     |-- SimpleDateFormat
  |     |-- DateTimeFormatter
  |-- Utility
        |-- Duration: 间隔(秒、纳秒)
        |-- Period: 间隔(年、月、日)
        |-- ChronoUnit: 间隔(所有单位)

ZonedDateTime 方法

方法 说明
static now() 当前时间
static ofXxxx(...) 指定时间
withXxx(time) 修改时间
minusXxx(time) 减少时间
plusXxx(time) 增加时间

Calendar 注意事项

  • 月份范围:0-11(1 月是 0)
  • 星期日是每周第一天

IO 流

字节流

java 复制代码
package com.anti.file.iostream;

import java.io.FileOutputStream;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("/Users/umi/Desktop/a.txt");
        fos.write(97); // writes 'a'
        fos.close();
    }
}

FileInputStream 读取:

  • read():每次读一个字节,末尾返回 -1
  • read(byte[] buffer):读入缓冲区,末尾返回 -1
java 复制代码
// 文件复制
FileInputStream fis = new FileInputStream("a.txt");
FileOutputStream fos = new FileOutputStream("b.txt");
byte[] bytes = new byte[1024 * 1024 * 5]; // 5MB buffer
int len;
while ((len = fis.read(bytes)) != -1) {
    fos.write(bytes, 0, len);
}
fos.close();
fis.close();

字符流

java 复制代码
package com.anti.file.iostream;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class FileWriterFileReader {
    public static void main(String[] args) throws IOException {
        String userDir = System.getProperty("user.dir");
        String url = userDir + "/src/com/anti/file/iostream/a.txt";
        FileWriter fw = new FileWriter(url, true);
        fw.write("I am Java");
        fw.close();

        FileReader fr = new FileReader(url);
        char[] chars = new char[1024];
        fr.read(chars);
        System.out.println(chars);
    }
}

字符流底层使用 8192 字节缓冲区,先从缓冲区读取,缓冲区空了再从文件读取。

缓冲流

java 复制代码
package com.anti.file.iostream;

import java.io.*;

public class BufferDemo {
    public static void main(String[] args) throws IOException {
        String userDir = System.getProperty("user.dir");
        String url = userDir + "/src/com/anti/file/iostream/a.txt";
        FileInputStream fis = new FileInputStream(url);
        BufferedInputStream bis = new BufferedInputStream(fis);
        int b = bis.read();
        System.out.println((char) b);
        bis.close();
    }
}

四种缓冲流:BufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWriter,内置 8192 字节缓冲区。BufferedReader.readLine()BufferedWriter.newLine() 是关键方法。

转换流(字符集转换)

java 复制代码
package com.anti.file.iostream;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.Charset;

public class ConversionStream {
    public static void main(String[] args) throws IOException {
        String userDir = System.getProperty("user.dir");
        String rUrl = userDir + "/src/com/anti/file/iostream/c.txt";
        String wUrl = userDir + "/src/com/anti/file/iostream/d.txt";
        FileReader fr = new FileReader(rUrl, Charset.forName("GBK"));
        FileWriter fw = new FileWriter(wUrl, Charset.forName("UTF-8"));
        int b;
        while ((b = fr.read()) != -1) { fw.write(b); }
        fr.close();
        fw.close();
    }
}

序列化

java 复制代码
package com.anti.file.iostream;

import com.anti.test.polymorphism.Person;
import java.io.*;

public class Serialization {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        String userDir = System.getProperty("user.dir");
        String path = userDir + "/src/com/anti/file/iostream/serialized.txt";

        // Serialize
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path));
        oos.writeObject(new Person("Zhang San", 18));
        oos.close();

        // Deserialize
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path));
        Person p = (Person) ois.readObject();
        System.out.println(p.toString());
        ois.close();
    }
}

序列化注意事项:

  • 必须实现 Serializable 接口
  • 使用 serialVersionUID 进行版本控制
  • transient 关键字可排除字段不被序列化

Commons-IO

java 复制代码
package com.anti.file.iostream;

import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

public class CommonsIoTest {
    public static void main(String[] args) throws IOException {
        String userDir = System.getProperty("user.dir");
        String path = userDir + "/src/com/anti/file/iostream/aaa/test.txt";
        FileUtils.touch(new File(path));

        ArrayList<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        FileUtils.writeLines(new File(path), list);
    }
}

File 类

java 复制代码
package com.anti.file;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;

public class Test {
    public static void main(String[] args) throws IOException {
        File file = new File("/Users/umi/Desktop");
        File[] files = file.listFiles();
        System.out.println(Arrays.toString(files));
    }
}

字节流 vs 字符流使用场景: 字节流用于复制任意文件,字符流用于读写纯文本文件。


多线程

线程状态

复制代码
NEW --> RUNNABLE --> TERMINATED
              |
              +--> BLOCKED(获取不到锁)
              +--> WAITING(wait 方法)
              +--> TIMED_WAITING(sleep 方法)

创建线程的三种方式

方式一:继承 Thread

java 复制代码
package com.anti.thread;

public class CustomThread extends Thread {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " started");
    }
}

方式二:实现 Runnable

java 复制代码
package com.anti.thread;

import java.util.Objects;

public class C2Thread implements Runnable {
    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        for (int i = 0; i < 10; i++) {
            System.out.println(name + " Runnable running " + i);
        }
    }
}

方式三:实现 Callable(可以有返回值)

java 复制代码
package com.anti.thread;

import java.util.concurrent.Callable;

public class CallableThread implements Callable<Integer> {
    @Override
    public Integer call() throws Exception { return 0; }
}

三种方式综合示例

java 复制代码
package com.anti.thread;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class ThreadDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 1. Extend Thread
        Thread t1 = new CustomThread();
        t1.setName("Thread-1");
        t1.start();

        // 2. Implement Runnable
        Thread t4 = new Thread(new C2Thread());
        t4.start();

        // 3. Implement Callable
        CallableThread myCallable = new CallableThread();
        FutureTask<Integer> futureTask = new FutureTask<>(myCallable);
        Thread t6 = new Thread(futureTask);
        t6.start();
        int result = futureTask.get();
        System.out.println("Result: " + result);
    }
}

同步:同步代码块

java 复制代码
package com.anti.thread;

public class TicketSyncBlock implements Runnable {
    static int tickets = 0;
    static Object obj = new Object();

    @Override
    public void run() {
        while (true) {
            synchronized (obj) {
                if (tickets < 100) {
                    tickets++;
                    System.out.println(Thread.currentThread().getName() + " selling ticket #" + tickets);
                } else { break; }
                try { Thread.sleep(10); }
                catch (InterruptedException e) { throw new RuntimeException(e); }
            }
        }
    }
}

同步:同步方法

java 复制代码
package com.anti.thread;

public class TicketSyncMethod implements Runnable {
    static int tickets = 0;

    @Override
    public void run() {
        while (true) { if (sellTicket()) break; }
    }

    private synchronized boolean sellTicket() {
        if (tickets < 100) {
            tickets++;
            System.out.println(Thread.currentThread().getName() + " selling ticket #" + tickets);
        } else { return true; }
        try { Thread.sleep(10); }
        catch (InterruptedException e) { throw new RuntimeException(e); }
        return false;
    }
}

同步:Lock 接口

java 复制代码
package com.anti.thread;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockDemo extends Thread {
    static int tickets = 0;
    static Lock lock = new ReentrantLock();

    @Override
    public void run() {
        while (true) {
            lock.lock();
            try {
                if (tickets < 100) {
                    tickets++;
                    System.out.println(Thread.currentThread().getName() + " selling ticket #" + tickets);
                } else { break; }
            } finally { lock.unlock(); }
            try { Thread.sleep(10); }
            catch (InterruptedException e) { throw new RuntimeException(e); }
        }
    }
}

线程属性

  • 优先级:范围 1-10,默认 5。不是绝对的,是概率问题
  • 守护线程setDaemon(true),所有非守护线程结束后自动结束
  • 插入线程t1.join(),当前线程等待 t1 执行完毕

线程池

使用 Executors:

java 复制代码
package com.anti.thread.threadpool;

import com.anti.thread.ThreadPoolTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolDemo {
    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(5);
        ThreadPoolTask task = new ThreadPoolTask();
        pool.submit(task);
        pool.submit(task);
        pool.shutdown();
    }
}

自定义 ThreadPoolExecutor:

java 复制代码
package com.anti.thread.threadpool;

import com.anti.thread.ThreadPoolTask;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class CustomThreadPool {
    public static void main(String[] args) {
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                4,                                    // core pool size
                8,                                    // max pool size
                60,                                   // keep-alive time
                TimeUnit.SECONDS,                     // time unit
                new ArrayBlockingQueue<>(5),          // work queue
                new ThreadPoolExecutor.AbortPolicy()  // rejection policy
        );
        ThreadPoolTask task = new ThreadPoolTask();
        pool.submit(task);
    }
}

线程池核心原理: 创建空线程池 → 提交任务时创建线程 → 任务完成后线程归还 → 无空闲线程时任务排队 → 队列满后创建临时线程 → 达到最大线程数后执行拒绝策略。

线程池大小建议:

  • CPU 密集型:最大并行数 + 1
  • IO 密集型:最大并行数 × 预期 CPU 利用率 × 总时间 / CPU 时间

生产者-消费者(等待/唤醒)

  • 消费者:检查桌子 → 没食物?等待 → 有食物?吃 → 唤醒生产者
  • 生产者:检查桌子 → 有食物?等待 → 没食物?做 → 放桌上 → 唤醒消费者

网络编程

网络三要素

  • IP 地址:设备在网络中的唯一标识
  • 端口号:应用程序在设备中的唯一标识
  • 协议:数据传输的规则(UDP、TCP、HTTP、HTTPS、FTP)

IP 地址

  • IPv4 有 2^32 个地址(已耗尽),IPv6 有 2^128 个地址
  • 特殊 IP:127.0.0.1(本机)
  • 常用命令:ipconfig(查看 IP)、ping(检测连通性)

UDP 通信

发送端:

java 复制代码
package com.anti.network.udp;

import java.io.IOException;
import java.net.*;

public class UdpDemo {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds = new DatagramSocket();
        String message = "hello world";
        byte[] bytes = message.getBytes();
        InetAddress inetAddress = InetAddress.getByName("127.0.0.1");
        DatagramPacket dp = new DatagramPacket(bytes, bytes.length, inetAddress, 8082);
        ds.send(dp);
        ds.close();
    }
}

接收端:

java 复制代码
package com.anti.network.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class Receiver {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds = new DatagramSocket(8082);
        while (true) {
            byte[] bytes = new byte[1024];
            DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
            ds.receive(dp);
            System.out.println(new String(dp.getData()));
        }
    }
}

TCP 通信

客户端:

java 复制代码
package com.anti.network.tcp;

import java.io.IOException;
import java.net.Socket;

public class Sender {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 10086);
        socket.getOutputStream().write("hello world".getBytes());
        socket.close();
    }
}

服务端:

java 复制代码
package com.anti.network.tcp;

import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class Receiver {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(10086);
        Socket socket = serverSocket.accept();
        InputStreamReader reader = new InputStreamReader(socket.getInputStream());
        int b;
        while ((b = reader.read()) != -1) {
            System.out.print((char) b);
        }
        reader.close();
        socket.close();
        serverSocket.close();
        System.out.println("reception complete");
    }
}

反射

获取 Class 对象的三种方式

java 复制代码
package com.anti.reflection;

public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        // Method 1: Class.forName
        Class<?> c1 = Class.forName("com.anti.reflection.Student");
        // Method 2: .class
        Class<?> c2 = Student.class;
        // Method 3: getClass()
        Student s = new Student();
        Class<?> c3 = s.getClass();

        System.out.println(c1.hashCode());
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());
    }
}

Student 类

java 复制代码
package com.anti.reflection;

public class Student {
    private String name;
    private int age;
    public int score;

    public Student() {
        System.out.println("no-arg constructor");
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("parameterized constructor");
    }

    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + "score" + score + "]";
    }
}

获取构造方法

java 复制代码
Constructor<?>[] cons1 = clazz.getConstructors();          // public only
Constructor<?>[] cons2 = clazz.getDeclaredConstructors();   // all including private
Constructor<?> con1 = clazz.getDeclaredConstructor();       // no-arg
Constructor<?> con2 = clazz.getDeclaredConstructor(String.class); // with String param

获取方法

java 复制代码
Method[] methods = clazz.getMethods();          // public including inherited
Method[] methods = clazz.getDeclaredMethods();   // all including private, not inherited
Method m = clazz.getDeclaredMethod("eat", String.class);
int modifiers = m.getModifiers();

获取字段

java 复制代码
Field field = clazz.getDeclaredField("name");
field.setAccessible(true);
field.set(student, "New Name");

动态代理

java 复制代码
Proxy.newProxyInstance(
    classLoader,
    interfaces,
    new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            return method.invoke(target, args);
        }
    }
);

正则表达式

符号 含义 示例
? 0 次或 1 次 \d?
* 0 次或多次 \d*
+ 1 次或多次 \d+
{n} 恰好 n 次 a{7}
{n,m} n 到 m 次 \d{7,19}
(?i) 忽略大小写 (?i)abc
java 复制代码
boolean matches = "hello".matches("h.*");
String[] parts = "a,b,,c".split(",");
String result = "a1b2c3".replaceAll("\\d", "_");

实战练习:随机点名器

java 复制代码
package com.anti.exercise;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

public class RandomRollCall {
    public static void main(String[] args) {
        ArrayList<String> arr = new ArrayList<>();
        Collections.addAll(arr, "fan", "jian", "cc", "bb", "aa");

        Random random = new Random();
        int index = random.nextInt(arr.size());
        System.out.println(arr.get(index));

        List<String> list = List.of("fan", "jian", "cc", "bb", "aa");
    }
}

Java 内存分配

区域 存储内容
方法运行时使用的内存
new 关键字创建的对象
方法区 字节码文件加载后的存储
本地方法栈 JVM 调用操作系统功能时使用
寄存器 CPU 寄存器

基本类型存储真实数据,引用类型存储地址值。

相关推荐
好好沉淀1 小时前
Spring @Validated和Validation注解 校验机制完全指南
java·数据库·后端
唐青枫1 小时前
Java RxJava 实战指南:从 Observable、Flowable 到线程切换和背压处理
java
Dobby_051 小时前
【CICD】Jenkins Pipeline 快速学习入门
运维·学习·jenkins
神秘的MT2 小时前
C# WinForm Socket 类 常用方法 (C# .NET,TCP 场景)
服务器·网络·学习·tcp/ip·c#·winform
凤山老林2 小时前
SpringBoot + Configuration2 实现配置的实时双向更新
java·spring boot·后端
艾莉丝努力练剑3 小时前
【MYSQL】MYSQL学习的一大重点:事务(上)- 原子性与持久性
android·数据库·学习·mysql·面试
丶玉面小蛟龙3 小时前
DGCNN网络学习
学习·点云·dgcnn
2601_963869954 小时前
【计算机毕业设计】基于 Spring Boot+Vue的手工体验馆管理系统的设计与实现
java·spring boot·后端
曹牧4 小时前
Java:BeanListHandler
java·数据库·oracle