# Java 核心基础

# 1. Java 语言概述

Java 是一种面向对象的编程语言,由 Sun Microsystems(现在是 Oracle 的一部分)于 1995 年发布。Java 的设计理念是"一次编写,到处运行"(Write Once, Run Anywhere,WORA),这使得 Java 程序可以在不同的平台上运行而不需要重新编译。

# 1.1 Java 的主要特性

  • 简单性:Java 语法基于 C++,但移除了指针、运算符重载等复杂特性
  • 面向对象:Java 是一种纯面向对象语言,除了基本数据类型外都是对象
  • 平台无关性:Java 程序通过 JVM 在不同平台上运行
  • 分布式:内置网络功能,支持分布式计算
  • 健壮性:强类型检查、自动内存管理、异常处理等特性
  • 安全性:安全管理器、类加载器、字节码验证器等安全机制
  • 多线程:内置多线程支持
  • 动态性:支持运行时类型识别和反射

# 1.2 Java 发展历史

版本 发布时间 主要特性
Java 1.0 1996 年 第一个官方版本
Java 1.2 1998 年 引入集合框架,Swing UI
Java 5 2004 年 泛型,注解,枚举,自动装箱拆箱
Java 8 2014 年 Lambda 表达式,Stream API,函数式接口
Java 11 2018 年 长期支持版本,HTTP 客户端
Java 17 2021 年 最新长期支持版本,密封类
Java 21 2023 年 虚拟线程,模式匹配,字符串模板

# 2. Java 语言基础

# 2.1 数据类型

Java 有两种数据类型:基本数据类型和引用数据类型。

# 基本数据类型

数据类型 大小 取值范围 默认值 示例
byte 1 字节 -128 到 127 0 byte b = 100;
short 2 字节 -32768 到 32767 0 short s = 1000;
int 4 字节 -2^31 到 2^31-1 0 int i = 100000;
long 8 字节 -2^63 到 2^63-1 0L long l = 100000L;
float 4 字节 IEEE754 0.0f float f = 3.14f;
double 8 字节 IEEE754 0.0d double d = 3.14;
char 2 字节 0 到 65535 '\u0000' char c = 'A';
boolean 1 位 true/false false boolean b = true;

# 引用数据类型

  • 类(Class)
  • 接口(Interface)
  • 数组(Array)
  • 枚举(Enum)
  • 注解(Annotation)

# 2.2 变量与常量

# 变量声明与初始化

// 声明变量
int age;
String name;

// 声明并初始化变量
int age = 25;
String name = "Java";

// 多个变量同时声明
int a, b, c = 10;  // a和b初始化为0,c初始化为10

# 常量声明

// 使用final关键字声明常量
final int MAX_AGE = 120;
final double PI = 3.14159;

// 静态常量(类常量)
public static final String COMPANY_NAME = "Oracle";

# 2.3 运算符

# 算术运算符

+, -, *, /, %, ++, --

int a = 10, b = 3;
int sum = a + b;       // 13
int diff = a - b;      // 7
int product = a * b;   // 30
int quotient = a / b;  // 3(整数除法)
int remainder = a % b; // 1

# 关系运算符

==, !=, >, <, >=, <=

boolean isEqual = (a == b);    // false
boolean isNotEqual = (a != b); // true
boolean isGreater = (a > b);   // true

# 逻辑运算符

&& (短路与), || (短路或), ! (非)

boolean result = (a > 5) && (b < 10);  // true
result = (a > 20) || (b < 5);          // true
result = !(a == b);                    // true

# 赋值运算符

=, +=, -=, *=, /=, %=

a += b;  // 等价于 a = a + b

# 位运算符

&, |, ^, ~, <<, >>, >>>

int x = 5;  // 二进制: 0101
int y = 3;  // 二进制: 0011
int z = x & y;  // 0001 (1)
z = x | y;      // 0111 (7)
z = x ^ y;      // 0110 (6)
z = ~x;         // 1010 (补码表示的-6)
z = x << 1;     // 1010 (10)
z = x >> 1;     // 0010 (2)
z = x >>> 1;    // 0010 (2)

# 2.4 流程控制

# 条件语句

// if-else语句
if (age > 18) {
    System.out.println("成年人");
} else if (age > 12) {
    System.out.println("青少年");
} else {
    System.out.println("儿童");
}

// switch语句
switch (day) {
    case 1: System.out.println("星期一"); break;
    case 2: System.out.println("星期二"); break;
    case 3: System.out.println("星期三"); break;
    case 4: System.out.println("星期四"); break;
    case 5: System.out.println("星期五"); break;
    case 6: System.out.println("星期六"); break;
    case 7: System.out.println("星期日"); break;
    default: System.out.println("无效的日期");
}

// Java 12+ switch表达式
String dayName = switch (day) {
    case 1 -> "星期一";
    case 2 -> "星期二";
    case 3 -> "星期三";
    case 4 -> "星期四";
    case 5 -> "星期五";
    case 6 -> "星期六";
    case 7 -> "星期日";
    default -> "无效的日期";
};

# 循环语句

// for循环
for (int i = 0; i < 10; i++) {
    System.out.println(i);
}

// 增强型for循环(for-each)
int[] numbers = {1, 2, 3, 4, 5};
for (int number : numbers) {
    System.out.println(number);
}

// while循环
int i = 0;
while (i < 10) {
    System.out.println(i);
    i++;
}

// do-while循环
int j = 0;
do {
    System.out.println(j);
    j++;
} while (j < 10);

// break和continue
for (int k = 0; k < 10; k++) {
    if (k == 5) break;  // 跳出循环
    if (k % 2 == 0) continue;  // 跳过本次循环的剩余部分
    System.out.println(k);
}

# 3. 面向对象编程

# 3.1 类与对象

# 类的定义

public class Person {
    // 成员变量(属性)
    private String name;
    private int age;
    private String address;
    
    // 构造方法
    public Person() {
        // 无参构造方法
    }
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // 成员方法(行为)
    public void setName(String name) {
        this.name = name;
    }
    
    public String getName() {
        return name;
    }
    
    public void setAge(int age) {
        if (age >= 0 && age <= 120) {
            this.age = age;
        }
    }
    
    public int getAge() {
        return age;
    }
    
    public void sayHello() {
        System.out.println("Hello, my name is " + name);
    }
}

# 对象的创建与使用

// 创建对象
Person person1 = new Person();
Person person2 = new Person("Alice", 25);

// 使用对象
person1.setName("Bob");
person1.setAge(30);
person1.sayHello();  // 输出: Hello, my name is Bob

System.out.println(person2.getName() + " is " + person2.getAge() + " years old.");

# 3.2 封装、继承与多态

# 封装

封装是将数据(属性)和方法(行为)组合在一个单元中,并控制对其的访问。Java 通过访问修饰符实现封装。

public class Student {
    // private成员变量,只能在类内部访问
    private String name;
    private int score;
    
    // public方法,提供对私有成员的访问
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public int getScore() {
        return score;
    }
    
    public void setScore(int score) {
        if (score >= 0 && score <= 100) {
            this.score = score;
        }
    }
}

# 继承

继承允许一个类(子类)继承另一个类(父类)的属性和方法。Java 中使用 extends 关键字实现继承。

// 父类
public class Animal {
    protected String name;
    
    public void eat() {
        System.out.println(name + " is eating.");
    }
    
    public void sleep() {
        System.out.println(name + " is sleeping.");
    }
}

// 子类
public class Dog extends Animal {
    public void bark() {
        System.out.println(name + " is barking.");
    }
    
    // 重写父类方法
    @Override
    public void eat() {
        System.out.println(name + " is eating bones.");
    }
}

// 使用
Dog dog = new Dog();
dog.name = "Rex";
dog.eat();  // 输出: Rex is eating bones.
dog.sleep();  // 输出: Rex is sleeping.
dog.bark();  // 输出: Rex is barking.

# 多态

多态允许使用父类引用指向子类对象,并根据对象的实际类型调用相应的方法。

Animal animal1 = new Animal();
Animal animal2 = new Dog();  // 多态:父类引用指向子类对象

animal1.eat();  // 调用Animal的eat()方法
animal2.eat();  // 调用Dog的eat()方法(方法重写)

// 向下转型
if (animal2 instanceof Dog) {
    Dog dog = (Dog) animal2;
    dog.bark();
}

# 3.3 抽象类与接口

# 抽象类

抽象类是不能实例化的类,可以包含抽象方法和普通方法。

public abstract class Shape {
    // 抽象方法(没有实现)
    public abstract double calculateArea();
    
    // 普通方法
    public void display() {
        System.out.println("Area: " + calculateArea());
    }
}

public class Circle extends Shape {
    private double radius;
    
    public Circle(double radius) {
        this.radius = radius;
    }
    
    @Override
    public double calculateArea() {
        return Math.PI * radius * radius;
    }
}

public class Rectangle extends Shape {
    private double width;
    private double height;
    
    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }
    
    @Override
    public double calculateArea() {
        return width * height;
    }
}

# 接口

接口定义了一组方法规范,不提供任何实现(Java 8 开始可以有默认方法和静态方法)。

public interface Drawable {
    void draw();  // 抽象方法
    
    // 默认方法(Java 8+)
    default void setup() {
        System.out.println("Setting up...");
    }
    
    // 静态方法(Java 8+)
    static void info() {
        System.out.println("This is a Drawable interface");
    }
}

public class Triangle implements Drawable {
    @Override
    public void draw() {
        System.out.println("Drawing a triangle");
    }
}

public class Square implements Drawable {
    @Override
    public void draw() {
        System.out.println("Drawing a square");
    }
    
    @Override
    public void setup() {
        System.out.println("Setting up square...");
    }
}

# 3.4 内部类

Java 允许在一个类内部定义另一个类,称为内部类。

# 成员内部类

public class Outer {
    private int outerVar = 1;
    
    public class Inner {
        private int innerVar = 2;
        
        public void display() {
            System.out.println("outerVar: " + outerVar);
            System.out.println("innerVar: " + innerVar);
        }
    }
    
    public void createInner() {
        Inner inner = new Inner();
        inner.display();
    }
}

// 使用
Outer outer = new Outer();
outer.createInner();

// 或
Outer.Inner inner = new Outer().new Inner();
inner.display();

# 静态内部类

public class Outer {
    private static int outerStaticVar = 3;
    private int outerVar = 4;
    
    public static class StaticInner {
        private int innerVar = 5;
        
        public void display() {
            System.out.println("outerStaticVar: " + outerStaticVar);
            // 不能访问非静态成员:System.out.println("outerVar: " + outerVar);
            System.out.println("innerVar: " + innerVar);
        }
    }
}

// 使用
Outer.StaticInner staticInner = new Outer.StaticInner();
staticInner.display();

# 局部内部类

public class Outer {
    public void method() {
        final int localVar = 6;
        
        // 局部内部类,定义在方法内部
        class LocalInner {
            public void display() {
                System.out.println("localVar: " + localVar);
            }
        }
        
        LocalInner localInner = new LocalInner();
        localInner.display();
    }
}

# 匿名内部类

public interface Greeting {
    void sayHello();
}

public class Main {
    public static void main(String[] args) {
        // 匿名内部类实现Greeting接口
        Greeting greeting = new Greeting() {
            @Override
            public void sayHello() {
                System.out.println("Hello from anonymous inner class");
            }
        };
        
        greeting.sayHello();
        
        // Lambda表达式(Java 8+)
        Greeting greeting2 = () -> System.out.println("Hello from lambda expression");
        greeting2.sayHello();
    }
}

# 4. 异常处理

# 4.1 异常分类

Java 中的异常分为两类:Checked Exception(受检异常)和 Unchecked Exception(非受检异常)。

  • Checked Exception:编译时检查的异常,必须显式处理或声明抛出
  • Unchecked Exception:运行时异常,继承自 RuntimeException,不需要显式处理

# 4.2 异常处理机制

# try-catch-finally

try {
    // 可能抛出异常的代码
    int result = 10 / 0;
} catch (ArithmeticException e) {
    // 处理特定异常
    System.out.println("除数不能为零: " + e.getMessage());
} catch (Exception e) {
    // 处理其他异常
    System.out.println("发生异常: " + e.getMessage());
} finally {
    // 无论是否发生异常都会执行的代码
    System.out.println("finally块执行");
}

# throws 和 throw

// throws声明方法可能抛出的异常
public void readFile(String filePath) throws FileNotFoundException, IOException {
    File file = new File(filePath);
    if (!file.exists()) {
        // throw抛出具体的异常
        throw new FileNotFoundException("文件不存在: " + filePath);
    }
    // 读取文件的代码
}

# 自定义异常

// 自定义受检异常
public class InsufficientFundsException extends Exception {
    private double amount;
    
    public InsufficientFundsException(double amount) {
        this.amount = amount;
    }
    
    public double getAmount() {
        return amount;
    }
}

// 自定义非受检异常
public class InvalidDataException extends RuntimeException {
    public InvalidDataException(String message) {
        super(message);
    }
}

# 5. 常用工具类

# 5.1 String 类

String str1 = "Hello";
String str2 = new String("Hello");

// 字符串连接
String str3 = str1 + " " + "World";
String str4 = str1.concat(" World");

// 字符串比较
boolean isEqual = str1.equals(str2);  // 内容比较,true
boolean isEqualRef = (str1 == str2);  // 引用比较,false
int compareResult = str1.compareTo(str2);  // 字典序比较,0

// 字符串查找
int index = str1.indexOf('l');  // 2
boolean contains = str1.contains("ell");  // true
boolean startsWith = str1.startsWith("He");  // true
boolean endsWith = str1.endsWith("lo");  // true

// 字符串截取
String substring = str1.substring(1, 4);  // "ell"

// 字符串转换
String upper = str1.toUpperCase();  // "HELLO"
String lower = str1.toLowerCase();  // "hello"
String trimmed = " Hello ".trim();  // "Hello"

// 字符串分割
String[] parts = "a,b,c".split(",");  // ["a", "b", "c"]

// 字符串格式化
String formatted = String.format("Name: %s, Age: %d", "Alice", 25);

# 5.2 包装类

Java 为每个基本数据类型提供了对应的包装类,用于在需要对象的场合使用基本数据类型。

基本数据类型 包装类
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean
// 自动装箱(基本类型转为包装类)
Integer i = 100;
Double d = 3.14;

// 自动拆箱(包装类转为基本类型)
int iValue = i;
double dValue = d;

// 字符串转基本类型
int num1 = Integer.parseInt("123");
double num2 = Double.parseDouble("3.14");

// 基本类型转字符串
String strNum1 = String.valueOf(123);
String strNum2 = Integer.toString(123);

# 5.3 Math 类

// 数学常量
double pi = Math.PI;  // 3.141592653589793
double e = Math.E;   // 2.718281828459045

// 基本运算
int abs = Math.abs(-10);  // 10
double max = Math.max(5.5, 3.3);  // 5.5
double min = Math.min(5.5, 3.3);  // 3.3
double pow = Math.pow(2, 3);  // 8.0
double sqrt = Math.sqrt(16);  // 4.0
long round = Math.round(3.7);  // 4
int floor = (int) Math.floor(3.7);  // 3
int ceil = (int) Math.ceil(3.7);  // 4

// 三角函数
double sin = Math.sin(Math.PI / 2);  // 1.0
double cos = Math.cos(Math.PI);  // -1.0
double tan = Math.tan(Math.PI / 4);  // 1.0

// 随机数
double random = Math.random();  // 0.0到1.0之间的随机数

# 5.4 Date 与时间类

Java 8 引入了新的日期和时间 API(java.time 包)。

// 获取当前日期和时间
LocalDate today = LocalDate.now();
LocalTime now = LocalTime.now();
LocalDateTime current = LocalDateTime.now();

// 创建特定日期和时间
LocalDate date = LocalDate.of(2023, 9, 25);
LocalTime time = LocalTime.of(14, 30, 45);
LocalDateTime dateTime = LocalDateTime.of(2023, 9, 25, 14, 30, 45);

// 日期时间操作
LocalDate tomorrow = today.plusDays(1);
LocalDate yesterday = today.minusDays(1);
boolean isAfter = tomorrow.isAfter(today);  // true
int year = today.getYear();  // 2023
Month month = today.getMonth();  // SEPTEMBER
int dayOfMonth = today.getDayOfMonth();  // 25
DayOfWeek dayOfWeek = today.getDayOfWeek();  // MONDAY

// 格式化和解析
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formattedDateTime = current.format(formatter);
LocalDateTime parsedDateTime = LocalDateTime.parse("2023-09-25 14:30:45", formatter);

// 时区
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
ZonedDateTime newYorkTime = ZonedDateTime.now(ZoneId.of("America/New_York"));

# 6. 集合框架

Java 集合框架提供了一组接口和类,用于存储和操作对象组。

# 6.1 集合框架概览

主要接口:

  • Collection:所有集合的根接口
    • List:有序集合,允许重复元素
    • Set:不允许重复元素
    • Queue:队列,通常按FIFO顺序处理元素
  • Map:映射接口,存储键值对

# 6.2 List 接口

// ArrayList:基于动态数组实现,查询快,增删慢
List<String> arrayList = new ArrayList<>();
arrayList.add("Java");
arrayList.add("Python");
arrayList.add("C++");
arrayList.add(1, "JavaScript");  // 在指定位置添加元素

// LinkedList:基于双向链表实现,查询慢,增删快
List<String> linkedList = new LinkedList<>();
linkedList.add("Java");
linkedList.add("Python");

// 遍历List
for (int i = 0; i < arrayList.size(); i++) {
    System.out.println(arrayList.get(i));
}

for (String language : arrayList) {
    System.out.println(language);
}

arrayList.forEach(System.out::println);

// List常用方法
boolean contains = arrayList.contains("Java");  // true
int index = arrayList.indexOf("Python");  // 2
String removed = arrayList.remove(1);  // 移除并返回指定位置的元素
arrayList.clear();  // 清空List

# 6.3 Set 接口

// HashSet:基于哈希表实现,无序,不重复
Set<String> hashSet = new HashSet<>();
hashSet.add("Java");
hashSet.add("Python");
hashSet.add("Java");  // 重复元素,不会被添加

// LinkedHashSet:基于哈希表和链表实现,有序(插入顺序),不重复
Set<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("Java");
linkedHashSet.add("Python");
linkedHashSet.add("C++");

// TreeSet:基于红黑树实现,有序(自然排序或自定义排序),不重复
Set<String> treeSet = new TreeSet<>();
treeSet.add("Java");
treeSet.add("Python");
treeSet.add("C++");  // 会自动排序

// 遍历Set
for (String language : hashSet) {
    System.out.println(language);
}

// Set常用方法
hashSet.contains("Java");  // true
hashSet.remove("Python");  // 移除元素
hashSet.clear();  // 清空Set

# 6.4 Map 接口

// HashMap:基于哈希表实现,无序,键不重复
Map<String, Integer> hashMap = new HashMap<>();
hashMap.put("Java", 1995);
hashMap.put("Python", 1991);
hashMap.put("C++", 1983);

// LinkedHashMap:基于哈希表和链表实现,有序(插入顺序),键不重复
Map<String, Integer> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("Java", 1995);
linkedHashMap.put("Python", 1991);
linkedHashMap.put("C++", 1983);

// TreeMap:基于红黑树实现,有序(键的自然排序或自定义排序),键不重复
Map<String, Integer> treeMap = new TreeMap<>();
treeMap.put("Java", 1995);
treeMap.put("Python", 1991);
treeMap.put("C++", 1983);  // 会按键自动排序

// 获取值
Integer javaYear = hashMap.get("Java");  // 1995

// 遍历Map
// 1. 遍历键
for (String key : hashMap.keySet()) {
    System.out.println(key + ": " + hashMap.get(key));
}

// 2. 遍历值
for (Integer value : hashMap.values()) {
    System.out.println(value);
}

// 3. 遍历键值对
for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {
    System.out.println(entry.getKey() + ": " + entry.getValue());
}

// 4. 使用Lambda表达式
hashMap.forEach((key, value) -> System.out.println(key + ": " + value));

// Map常用方法
hashMap.containsKey("Java");  // true
hashMap.containsValue(1995);  // true
hashMap.remove("Python");  // 移除键值对
hashMap.clear();  // 清空Map

# 6.5 集合工具类 Collections

// 排序
List<Integer> numbers = new ArrayList<>(Arrays.asList(3, 1, 4, 1, 5, 9));
Collections.sort(numbers);  // 升序排序
Collections.sort(numbers, Collections.reverseOrder());  // 降序排序

// 查找
int max = Collections.max(numbers);  // 9
int min = Collections.min(numbers);  // 1
int index = Collections.binarySearch(numbers, 5);  // 二分查找

// 替换
Collections.fill(numbers, 0);  // 用0替换所有元素
Collections.replaceAll(numbers, 0, 10);  // 用10替换所有0

// 反转
Collections.reverse(numbers);

// 随机打乱
Collections.shuffle(numbers);

// 同步集合(线程安全)
List<String> synchronizedList = Collections.synchronizedList(new ArrayList<>());
Map<String, Integer> synchronizedMap = Collections.synchronizedMap(new HashMap<>());

# 7. 泛型

泛型允许在定义类、接口和方法时使用类型参数,提高代码的类型安全性和可重用性。

# 7.1 泛型类

public class Box<T> {
    private T content;
    
    public void setContent(T content) {
        this.content = content;
    }
    
    public T getContent() {
        return content;
    }
}

// 使用泛型类
Box<String> stringBox = new Box<>();
stringBox.setContent("Hello");
String content = stringBox.getContent();

Box<Integer> integerBox = new Box<>();
integerBox.setContent(123);
Integer number = integerBox.getContent();

# 7.2 泛型接口

public interface List<T> {
    void add(T element);
    T get(int index);
    // 其他方法
}

// 实现泛型接口
public class ArrayList<T> implements List<T> {
    // 实现方法
}

# 7.3 泛型方法

public class Util {
    public static <T> void printArray(T[] array) {
        for (T element : array) {
            System.out.print(element + " ");
        }
        System.out.println();
    }
    
    public static <T extends Comparable<T>> T max(T a, T b) {
        return a.compareTo(b) > 0 ? a : b;
    }
}

// 使用泛型方法
Integer[] intArray = {1, 2, 3, 4, 5};
String[] strArray = {"Hello", "World"};
Util.printArray(intArray);
Util.printArray(strArray);

Integer maxInt = Util.max(5, 10);
String maxStr = Util.max("Apple", "Banana");

# 7.4 泛型通配符

// 上界通配符:? extends T,表示可以接受T或T的子类
public void printList(List<? extends Number> list) {
    for (Number number : list) {
        System.out.println(number);
    }
}

// 下界通配符:? super T,表示可以接受T或T的父类
public void addNumbers(List<? super Integer> list) {
    list.add(1);
    list.add(2);
    list.add(3);
}

// 无限通配符:?,表示可以接受任意类型
public void processList(List<?> list) {
    for (Object obj : list) {
        System.out.println(obj);
    }
}

// 使用
List<Integer> intList = Arrays.asList(1, 2, 3);
List<Double> doubleList = Arrays.asList(1.1, 2.2, 3.3);
List<String> strList = Arrays.asList("A", "B", "C");

printList(intList);  // 可以
printList(doubleList);  // 可以
// printList(strList);  // 编译错误

List<Number> numberList = new ArrayList<>();
addNumbers(numberList);  // 可以
addNumbers(intList);  // 可以

processList(intList);  // 可以
processList(doubleList);  // 可以
processList(strList);  // 可以

# 8. 输入输出

Java 的 I/O 系统通过 java.io 包提供,主要包括字节流和字符流。

# 8.1 字节流

字节流用于处理二进制数据,主要类有 InputStream 和 OutputStream。

// 文件读取(字节流)
try (FileInputStream fis = new FileInputStream("input.txt")) {
    int data;
    while ((data = fis.read()) != -1) {
        System.out.print((char) data);
    }
} catch (IOException e) {
    e.printStackTrace();
}

// 文件写入(字节流)
try (FileOutputStream fos = new FileOutputStream("output.txt")) {
    String content = "Hello, World!";
    fos.write(content.getBytes());
} catch (IOException e) {
    e.printStackTrace();
}

// 缓冲字节流
// 使用BufferedInputStream和BufferedOutputStream提高读写效率
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("input.txt"));
     BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("output.txt"))) {
    int data;
    while ((data = bis.read()) != -1) {
        bos.write(data);
    }
} catch (IOException e) {
    e.printStackTrace();
}

# 8.2 字符流

字符流用于处理文本数据,主要类有 Reader 和 Writer。

// 文件读取(字符流)
try (FileReader fr = new FileReader("input.txt")) {
    int data;
    while ((data = fr.read()) != -1) {
        System.out.print((char) data);
    }
} catch (IOException e) {
    e.printStackTrace();
}

// 文件写入(字符流)
try (FileWriter fw = new FileWriter("output.txt")) {
    String content = "Hello, World!";
    fw.write(content);
} catch (IOException e) {
    e.printStackTrace();
}

// 缓冲字符流
// 使用BufferedReader和BufferedWriter提高读写效率
try (BufferedReader br = new BufferedReader(new FileReader("input.txt"));
     BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) {
    String line;
    while ((line = br.readLine()) != null) {
        bw.write(line);
        bw.newLine();
    }
} catch (IOException e) {
    e.printStackTrace();
}

# 8.3 Java 7 的 try-with-resources

Java 7 引入了 try-with-resources 语句,简化了资源管理。

// try-with-resources语句自动关闭实现了AutoCloseable接口的资源
try (FileInputStream fis = new FileInputStream("input.txt");
     FileOutputStream fos = new FileOutputStream("output.txt")) {
    int data;
    while ((data = fis.read()) != -1) {
        fos.write(data);
    }
} catch (IOException e) {
    e.printStackTrace();
}

# 8.4 NIO

Java NIO(New I/O)是 Java 4 引入的一个替代标准 I/O API 的库,提供了更高效的 I/O 操作。

// NIO Path和Files
Path filePath = Paths.get("input.txt");

// 读取文件所有行
List<String> lines = Files.readAllLines(filePath, StandardCharsets.UTF_8);
for (String line : lines) {
    System.out.println(line);
}

// 写入文件
List<String> content = Arrays.asList("Line 1", "Line 2", "Line 3");
Files.write(Paths.get("output.txt"), content, StandardCharsets.UTF_8);

// 复制文件
Files.copy(Paths.get("input.txt"), Paths.get("input_copy.txt"), StandardCopyOption.REPLACE_EXISTING);

// 创建目录
Files.createDirectories(Paths.get("dir/subdir"));

// 检查文件是否存在
boolean exists = Files.exists(filePath);

# 9. 多线程编程

Java 提供了内置的多线程支持,通过 Thread 类和 Runnable 接口实现。

# 9.1 创建线程

// 方式1:继承Thread类
class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("Thread is running: " + Thread.currentThread().getName());
    }
}

// 方式2:实现Runnable接口
class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("Runnable is running: " + Thread.currentThread().getName());
    }
}

// 启动线程
MyThread thread1 = new MyThread();
thread1.start();

Thread thread2 = new Thread(new MyRunnable());
thread2.start();

// 方式3:使用Lambda表达式(Java 8+)
Thread thread3 = new Thread(() -> {
    System.out.println("Lambda thread is running: " + Thread.currentThread().getName());
});
thread3.start();

# 9.2 线程状态

Java 线程有以下状态:

  • NEW:新建状态
  • RUNNABLE:就绪状态
  • RUNNING:运行状态
  • BLOCKED:阻塞状态
  • WAITING:等待状态
  • TIMED_WAITING:超时等待状态
  • TERMINATED:终止状态

# 9.3 线程控制

// 线程休眠
try {
    Thread.sleep(1000);  // 休眠1000毫秒
} catch (InterruptedException e) {
    e.printStackTrace();
}

// 线程优先级
thread1.setPriority(Thread.MAX_PRIORITY);  // 10
thread2.setPriority(Thread.MIN_PRIORITY);  // 1
thread3.setPriority(Thread.NORM_PRIORITY);  // 5

// 线程等待与通知
// wait()和notify()/notifyAll()方法必须在同步代码块或同步方法中使用
synchronized (object) {
    try {
        object.wait();  // 等待通知
        // 或等待指定时间
        // object.wait(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

synchronized (object) {
    object.notify();  // 唤醒一个等待的线程
    // 或唤醒所有等待的线程
    // object.notifyAll();
}

// 线程中断
thread1.interrupt();
if (Thread.interrupted()) {
    // 线程被中断
}

// 线程等待(join)
try {
    thread1.join();  // 等待thread1执行完毕
    // 或等待指定时间
    // thread1.join(1000);
} catch (InterruptedException e) {
    e.printStackTrace();
}

# 9.4 线程安全

线程安全是指多线程环境下,程序能够正确地执行,不会出现数据不一致或其他异常情况。

// 同步代码块
synchronized (this) {
    // 线程安全的代码
}

// 同步方法
public synchronized void synchronizedMethod() {
    // 线程安全的代码
}

// 显式锁(ReentrantLock)
Lock lock = new ReentrantLock();
lock.lock();
try {
    // 线程安全的代码
} finally {
    lock.unlock();  // 确保释放锁
}

// 线程安全的集合
List<String> synchronizedList = Collections.synchronizedList(new ArrayList<>());
Map<String, Integer> concurrentHashMap = new ConcurrentHashMap<>();

// 原子变量
AtomicInteger count = new AtomicInteger(0);
count.incrementAndGet();  // 原子递增
count.addAndGet(10);  // 原子增加指定值

# 10. 反射

反射机制允许程序在运行时获取类的信息、创建类的实例、调用类的方法和访问类的属性。

// 获取Class对象
Class<?> clazz1 = Class.forName("java.lang.String");
Class<?> clazz2 = String.class;
String str = "Hello";
Class<?> clazz3 = str.getClass();

// 获取类信息
String className = clazz1.getName();  // 类名
Package pkg = clazz1.getPackage();  // 包
Class<?> superClass = clazz1.getSuperclass();  // 父类
Class<?>[] interfaces = clazz1.getInterfaces();  // 实现的接口

// 获取构造方法
Constructor<?>[] constructors = clazz1.getDeclaredConstructors();
Constructor<?> constructor = clazz1.getConstructor(String.class);

// 创建实例
Object obj = constructor.newInstance("Hello");

// 获取方法
Method[] methods = clazz1.getDeclaredMethods();
Method method = clazz1.getMethod("length");

// 调用方法
Object result = method.invoke(obj);  // 5

// 获取字段
Field[] fields = clazz1.getDeclaredFields();
Field field = clazz1.getDeclaredField("value");
field.setAccessible(true);  // 设置为可访问私有字段

// 访问字段
Object value = field.get(obj);  // 字符数组
field.set(obj, "World".toCharArray());  // 修改私有字段的值

// 获取注解
Annotation[] annotations = clazz1.getAnnotations();
Annotation annotation = clazz1.getAnnotation(Deprecated.class);

# 11. 枚举与注解

# 11.1 枚举

枚举是一种特殊的类,用于表示固定数量的常量。

// 简单枚举
enum Weekday {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

// 使用枚举
Weekday today = Weekday.MONDAY;
switch (today) {
    case MONDAY:
        System.out.println("星期一");
        break;
    case FRIDAY:
        System.out.println("星期五");
        break;
    default:
        System.out.println("其他天");
}

// 带属性和方法的枚举
enum Season {
    SPRING("春季", 1),
    SUMMER("夏季", 2),
    AUTUMN("秋季", 3),
    WINTER("冬季", 4);
    
    private final String name;
    private final int code;
    
    Season(String name, int code) {
        this.name = name;
        this.code = code;
    }
    
    public String getName() {
        return name;
    }
    
    public int getCode() {
        return code;
    }
}

// 使用带属性和方法的枚举
Season season = Season.SPRING;
System.out.println(season.getName() + ": " + season.getCode());  // 春季: 1

# 11.2 注解

注解是一种特殊的接口,用于提供元数据。

// 预定义注解
@Override  // 标记方法重写
@Deprecated  // 标记已过时的方法或类
@SuppressWarnings("unchecked")  // 抑制编译器警告

// 自定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Log {
    String value() default "";
    boolean enabled() default true;
}

// 使用自定义注解
public class UserService {
    @Log("登录操作")
    public void login(String username, String password) {
        // 登录逻辑
    }
    
    @Log(value = "注销操作", enabled = false)
    public void logout(String username) {
        // 注销逻辑
    }
}

// 通过反射获取注解信息
Class<?> serviceClass = UserService.class;
Method[] methods = serviceClass.getDeclaredMethods();
for (Method method : methods) {
    if (method.isAnnotationPresent(Log.class)) {
        Log logAnnotation = method.getAnnotation(Log.class);
        System.out.println("方法: " + method.getName());
        System.out.println("日志: " + logAnnotation.value());
        System.out.println("启用: " + logAnnotation.enabled());
    }
}

# 12. Java 各版本新特性

Java 语言自发布以来不断发展,每个主要版本都带来了重要的特性和改进。本节提供了各主要 Java 版本新特性的概览,详细内容请参考以下链接文档:

# 12.1 Java 8 新特性

Java 8 于 2014 年 3 月发布,引入了函数式编程支持、Stream API、新的日期时间 API 等重要特性。

详细内容请查看:Java 8 新特性文档

# 12.2 Java 11 新特性

Java 11 是 Java 编程语言的一个长期支持(LTS)版本,于 2018 年 9 月发布。作为继 Java 8 之后的第二个 LTS 版本,Java 11 带来了性能优化、新的 API、工具增强等改进。

详细内容请查看:Java 11 新特性文档

# 12.3 Java 17 新特性

Java 17 是 Java 编程语言的一个长期支持(LTS)版本,于 2021 年 9 月发布。作为继 Java 11 之后的第三个 LTS 版本,Java 17 带来了密封类、模式匹配、新的垃圾收集器等特性。

详细内容请查看:Java 17 新特性文档

# 12.4 Java 21 新特性

Java 21 是 Java 编程语言的一个长期支持(LTS)版本,于 2023 年 9 月发布。作为继 Java 17 之后的第四个 LTS 版本,Java 21 带来了虚拟线程、记录模式、开关表达式增强等重要特性。

详细内容请查看:Java 21 新特性文档