Java语法速查笔记:快速掌握90%日常开发语法点

本文整理自《Java入门到精通》,覆盖日常开发90%以上的语法点,包括基础语法、数据类型、运算符、流程控制、面向对象、异常、泛型、集合、IO、Lambda、Stream等,适合快速翻阅,不适合零基础精读。

整理自《Java入门到精通》,覆盖日常开发90%以上的语法点。适合快速翻阅,不适合零基础精读。

一、第一个程序 & 开发环境

将下面代码保存到 HelloWorld.java 文件:

// 文件名必须与 public class 同名
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, Java!");
    }
}

编译与运行:

javac HelloWorld.java    # 编译 → HelloWorld.class
java HelloWorld          # 运行(不用写.class)

几个常识:

  • 一个 .java文件最多一个 public class,但可以有多个非 public 类

  • main 方法签名固定,少一个 static 都不行

  • Java 11+ 可以 java HelloWorld.java 直接运行单个源文件(省掉 javac)

二、最基础的知识

2.1 注释

// 单行注释

/*
 * 多行注释
 */

/**
 * 文档注释(会被 javadoc 提取生成 API 文档)
 * @param name 名字
 * @return 问候语
 */
public String sayHello(String name) { ... }

2.2 标识符 & 关键字

规则说明
组成

字母、数字、下划线 _、美元符 $

首字符不能是数字
大小写严格区分,name 和 Name 是两个东西
关键字class、public、static 等 50 个保留字,不能用做标识符

命名约定(不强制但大家都这么写):

  • 类/接口:PascalCase → HelloWorld、Runnable

  • 方法/变量:camelCase → getUserName、userCount

  • 常量:UPPER_SNAKE → MAX_SIZE

  • 包名:全小写 → com.example.utils

2.3 变量声明

int age = 18;                    // 基本类型
String name = "张三";            // 引用类型
var list = new ArrayList<>();    // Java 10+ 局部变量类型推断

// 常量:final 修饰,只能赋值一次
final double PI = 3.14159;
final String APP_NAME = "MyApp";

Java 10 的 var 注意事项:

  • 只能用于局部变量(有初始化表达式),不能做字段/参数/返回值类型

  • 代码 var x = null; 编译报错(推断不出类型)

  • 代码 var list = new ArrayList<>() 将被推断为 ArrayList<Object> 类型,注意类型安全

2.4 类型转换

// 自动转换(小 → 大):byte → short → int → long → float → double
int a = 100;
long b = a;   // OK,自动提升,不丢失数据

// 强制转换(大 → 小):可能丢数据
double d = 3.14;
int i = (int) d;   // 3,小数部分没了

// 包装类转换
String s = "123";
int n = Integer.parseInt(s);        // String → int
String s2 = String.valueOf(456);    // int → String

三、数据类型

3.1 基本类型(8种)

类型大小范围默认值包装类

byte

1字节-128 ~ 1270Byte

short

2字节-215 ~ 215-10Short

int

4字节-231 ~ 231-10Integer

long

8字节-263 ~ 263-10LLong

float

4字节IEEE 7540.0fFloat

double

8字节IEEE 7540.0dDouble

char

2字节0 ~ 65535'\u0000'Character

boolean

JVM决定true/falsefalseBoolean

简单示例:

long money = 100_000_000L;   // L 后缀,JDK7+ 支持下划线分割,更容易阅读
float pi = 3.14f;            // f/F 后缀
double e = 2.71828;          // 不加后缀默认 double
char ch = 'A';
boolean flag = true;

3.2 字符串 String

String 是引用类型(不可变对象),但用起来像基本类型。

String s1 = "hello";                    // 字面量,存常量池
String s2 = new String("hello");        // 强制在堆上新开辟

// 常用方法
"hello".length();                       // 5 字符串长度
"hello".charAt(1);                      // 'e' 下标为1的字符
"hello".substring(1, 3);                // "el"(左闭右开)
"hello".contains("ll");                 // true 是否包含“ll”子字符串
"hello".indexOf("l");                   // 2 首次“l”出现的下标
"hello".toUpperCase();                  // "HELLO" 转换成大写
"  abc  ".trim();                       // "abc" 去除首尾空白
"a,b,c".split(",");                     // ["a","b","c"] 根据“,”分隔
String.join("-", "a", "b", "c");        // "a-b-c"

// 比较(重要!)
"abc".equals("abc");                    // true —— 值比较
"abc" == "abc";                         // true(常量池),但不要依赖 ==
"abc" == new String("abc");             // false —— 地址不同

// 拼接:编译器自动优化为 StringBuilder
String s = "Hello " + "World";
String s = "Age: " + 18;               // 自动转换

// 格式化
String.format("Hello %s, age %d", "Tom", 20);  // "Hello Tom, age 20"
"Hello %s, age %d".formatted("Tom", 20);       // Java 15+

StringBuilder(非线程安全,常用)/ StringBuffer(线程安全,性能稍逊):

StringBuilder sb = new StringBuilder();
sb.append("Hello").append(" ").append("World");
sb.insert(5, ",");
sb.toString();  // "Hello, World"

3.3 数组

// 声明
int[] arr1 = new int[5];            // 默认全0
int[] arr2 = {1, 2, 3, 4, 5};       // 直接初始化
int[] arr3 = new int[]{1, 2, 3};

// 二维数组
int[][] matrix = {{1,2}, {3,4}, {5,6}};

// 常用操作
arr1.length;                           // 5(属性不是方法)数组长度
Arrays.toString(arr2);                 // "[1, 2, 3, 4, 5]" 
Arrays.sort(arr2);                     // 原地排序
Arrays.binarySearch(arr2, 3);          // 二分查找(需先排序)
int[] copy = Arrays.copyOf(arr2, 10);  // 扩容/截取
Arrays.fill(arr1, 0);                  // 全部填0

3.4 包装类 & 自动装箱拆箱

Integer i = 100;          // 自动装箱:Integer.valueOf(100)
int j = i;                // 自动拆箱:i.intValue()

// 缓存坑(-128 ~ 127 内走缓存池,== 返回 true)
Integer a = 127, b = 127;
System.out.println(a == b);    // true

Integer c = 128, d = 128;
System.out.println(c == d);    // false —— 超出缓存范围

四、运算符

4.1 算术 & 比较 & 逻辑

int r = a + b;      // 加
int r = a - b;      // 减
int r = a * b;      // 乘
int r = a / b;      // 除(整数除得整数,7/2=3)
int r = a % b;      // 取余

a == b; a != b; a > b; a < b; a >= b; a <= b;

// 短路逻辑:&& 遇 false 停止,|| 遇 true 停止
boolean r = a > 0 && b > 10;       // && 短路与
boolean r = a > 0 || b > 10;       // || 短路或
boolean r = !flag;                 // 取反

4.2 位运算

int r = a & b;       // 位与
int r = a | b;       // 位或
int r = a ^ b;       // 异或
int r = ~a;          // 取反
int r = a << 2;      // 左移(乘以2^2)
int r = a >> 2;      // 右移(除以2^2,保留符号位)
int r = a >>> 2;     // 无符号右移

4.3 赋值 & 三元

a += b;    // a = a + b
a -= b;    // a = a - b
a *= b;    // a = a * b
a /= b;    // a = a / b
a %= b;    // a = a % b
a++;       // 后置自增
++a;       // 前置自增

// 三元运算符
// 如果 a > b 为 true,则 max 为 a
// 如果 a > b 为 false,则 max 为 b
int max = a > b ? a : b;

4.4 instanceof(类型判断)

// 判断变量 obj 是不是字符串类型;如果是,自动转型,把值给到变量 s,在 if 里面直接当做 String 使用
Object obj = "hello";
if (obj instanceof String s) {   // Java 16+ 模式匹配
    System.out.println(s.toUpperCase());
}

五、流程控制

5.1 条件分支

// if-else
if (score >= 90) {
    grade = 'A';
} else if (score >= 80) {
    grade = 'B';
} else {
    grade = 'C';
}

// switch(支持 int/String/枚举/char/byte/short)
// Java 14+ 箭头语法
switch (day) {
    case MONDAY, FRIDAY -> System.out.println("工作日");
    case SATURDAY, SUNDAY -> System.out.println("周末");
    default -> System.out.println("未知");
}

// switch 表达式(Java 14+,可以有返回值)
String result = switch (status) {
    case 1 -> "成功";
    case 2, 3 -> "处理中";
    default -> "未知";
};

5.2 循环

// for(确定次数)
for (int i = 0; i < 10; i++) {
    System.out.println(i);
}

// 增强 for(遍历数组/集合)
for (String s : list) {
    System.out.println(s);
}

// while(条件满足就循环)
while (condition) {
    // ...
}

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

// break:跳出当前循环
// continue:跳过本次循环,继续下一次
// 带标签的 break/continue(跳出多层)
outer:
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        if (i == 1 && j == 1) break outer; // 跳出外层循环
    }
}

5.3 输入输出

import java.util.Scanner;

Scanner sc = new Scanner(System.in);
String name = sc.nextLine();        // 读一行
int age = sc.nextInt();             // 读整数
double score = sc.nextDouble();     // 读浮点数
sc.close(); // 是否资源

六、方法

6.1 定义与调用

// [修饰符] 返回类型 方法名([参数列表]) {
//     方法体
// }

public static int add(int a, int b) {
    return a + b;
}

// 调用方法
int result = add(3, 5);

6.2 参数传递

Java 只有值传递:

  • 基本类型:传的是值的副本,不影响原值

  • 引用类型:传的是地址的副本,可以通过它改对象内容,但不能让形参指向新对象

// 不影响原值
void change(int x) {
    x = 10;
}

// 影响了原对象
void change(StringBuilder sb) {
    sb.append("!");
}

// 不影响原引用
void change(StringBuilder sb) {
    sb = new StringBuilder();
}

6.3 方法重载(Overload)

同一个类中,方法名相同、参数列表不同(类型/个数/顺序),与返回值无关。

int max(int a, int b) { ... }

int max(int a, int b, int c) { ... }

double max(double a, double b) { ... }

6.4 可变参数

public int sum(int... nums) {   // 本质是数组
    int total = 0;
    for (int n : nums) total += n;
    return total;
}
sum(1, 2, 3);   // 6
sum();          // 0

// 如果一个方法既有普通参数又有可变参数,可变参数必须放最后
public void print(String prefix, int... nums) { ... }

6.5 递归

public long factorial(int n) {
    if (n <= 1) return 1;
    return n * factorial(n - 1);
}

七、面向对象

7.1 类与对象

public class Person {
    // 字段(成员变量)
    private String name;
    private int age;

    // 构造方法
    public Person() {}                           // 无参
    public Person(String name, int age) {         // 有参
        this.name = name;
        this.age = age;
    }

    // getter / setter
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    // 普通方法
    public void sayHello() {
        System.out.println("我是" + name + ",今年" + age);
    }

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

// 使用
Person p = new Person("张三", 20);
p.sayHello();

7.2 封装

用 private 隐藏内部状态,通过 public 的 getter/setter 控制访问。

修饰符本类同包子类其他包

private




default (不写)



protected


public

7.3 继承

// Java 只能单继承(一个子类只能有一个父类)
public class Student extends Person {
    private String school;

    public Student(String name, int age, String school) {
        super(name, age);   // 调用父类构造,必须在第一行
        this.school = school;
    }

    // 方法重写(Override)—— 方法签名必须完全一致
    @Override
    public void sayHello() {
        super.sayHello();   // 可调父类版本
        System.out.println("我在" + school + "上学");
    }
}

super关键字:

  • super() —— 调用父类构造

  • super.method() —— 调用父类方法

  • super.field —— 访问父类字段

final修饰:

  • final class —— 不能被继承(如 String)

  • final 方法 —— 不能被子类重写

  • final 变量 —— 常量

7.4 多态

// 编译看左边,运行看右边
Person p = new Student("小明", 18, "清华");
p.sayHello();   // 调用的是 Student 重写后的版本

// instanceof 判断实际类型
if (p instanceof Student s) {
    System.out.println(s.getSchool());
}

7.5 抽象类

public abstract class Animal {
    protected String name;

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

    // 抽象方法:没有方法体,子类必须实现
    public abstract void makeSound();

    // 普通方法(可以被子类直接用)
    public void eat() {
        System.out.println(name + "在吃东西");
    }
}

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

    @Override
    public void makeSound() {
        System.out.println("喵喵喵");
    }
}

7.6 接口

// Java 8+ 接口可以有 default 方法和 static 方法
public interface Flyable {
    // 常量(默认 public static final)
    int MAX_SPEED = 300;

    // 抽象方法(默认 public abstract)
    void fly();

    // Java 8:默认方法(有实现,子类可选重写)
    default void land() {
        System.out.println("降落中...");
    }

    // Java 8:静态方法(属于接口本身)
    static boolean canFly(int speed) {
        return speed > 0 && speed <= MAX_SPEED;
    }

    // Java 9:私有方法(给 default 方法复用内部逻辑)
    private void check() { ... }
}

// 一个类可以实现多个接口
public class Bird extends Animal implements Flyable, Runnable {
    @Override
    public void fly() { ... }
    @Override
    public void run() { ... }
}

抽象类 vs 接口:


抽象类接口
继承

单继承 extends

多实现 implements

构造方法没有
字段可以有普通字段只能有常量
方法抽象 + 具体都行抽象 + default + static
用途模板(is-a 关系)能力契约(can-do 关系)

7.7 内部类

public class Outer {
    private String name = "外部";

    // 成员内部类
    class Inner {
        void print() { System.out.println(name); }
    }

    // 静态内部类(不依赖外部类实例)
    static class StaticInner {
        void print() { System.out.println("静态内部类"); }
    }

    // 局部内部类(方法里定义)
    void method() {
        class LocalInner {
            void print() { System.out.println("局部内部类"); }
        }
    }

    // 匿名内部类(Lambda 出现前用得很多)
    Runnable r = new Runnable() {
        @Override
        public void run() { System.out.println("匿名内部类"); }
    };
}

7.8 记录类 Record(Java 16+)

不可变数据载体,自动生成构造器、getter、equals、hashCode、toString:

public record Point(int x, int y) {}

Point p = new Point(3, 5);
int x = p.x();    // 自动生成的访问器
System.out.println(p);  // Point[x=3, y=5]

八、异常处理

8.1 异常体系

Throwable
├── Error(严重问题,一般不管)
│   ├── OutOfMemoryError 内存溢出异常
│   └── StackOverflowError 堆栈溢出异常
└── Exception
    ├── RuntimeException(非检查异常,编译不强制处理)
    │   ├── NullPointerException  空指针异常
    │   ├── IndexOutOfBoundsException  下标越界异常
    │   ├── ArithmeticException  非法数学运算异常
    │   └── IllegalArgumentException  非法参数异常
    └── 其他(检查异常,编译期强制处理)
        ├── IOException  IO异常
        ├── SQLException  SQL异常
        └── ClassNotFoundException  类没有找到异常

8.2 try-catch-finally

try {
    int r = 10 / 0;                    // 抛 ArithmeticException
} catch (ArithmeticException e) {
    System.out.println("算术异常:" + e.getMessage());
} catch (Exception e) {
    e.printStackTrace();               // 子类在前,父类在后
} finally {
    System.out.println("始终执行");     // 除非 System.exit(0)
}

8.3 try-with-resources(Java 7+)

资源用完后自动调用 close(),省掉 finally 的样板代码:

// Java 7写法:在 try() 里声明资源
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
    String line;
    while ((line = br.readLine()) != null) {
        System.out.println(line);
    }
} catch (IOException e) {
    e.printStackTrace();
}

// Java 9 改进:可以用外部声明的 final/effectively final 变量
BufferedReader r = new BufferedReader(new FileReader("file.txt"));
try (r) { ... }

8.4 throw / throws

// throws:声明方法可能抛异常
public void readFile(String path) throws IOException {
    // throw:实际抛出异常
    if (path == null) throw new IllegalArgumentException("路径不能为空");
    // ...
}

九、泛型

9.1 基础

泛型本质是类型参数化,让代码在编译期就保证类型安全。

// 泛型类
public class Box<T> {
    private T content;
    public T get() { return content; }
    public void set(T content) { this.content = content; }
}

Box<String> stringBox = new Box<>();
stringBox.set("Hello");
// stringBox.set(123);   // 编译错误!

// 泛型方法
public static <T> T first(List<T> list) {
    return list.get(0);
}

// 泛型接口
public interface Comparator<T> {
    int compare(T a, T b);
}

9.2 通配符

// ? —— 无界通配符
void printList(List<?> list) {
    for (Object o : list) System.out.println(o);
}

// ? extends T —— 上界(生产/读,get 出来的都是 T 或 T 的子类)
void readNumbers(List<? extends Number> list) {
    Number n = list.get(0);   // OK
    // list.add(1);           // 编译错误,不知道具体子类型
}

// ? super T —— 下界(消费/写,能往里放 T 或 T 的子类)
void addNumbers(List<? super Integer> list) {
    list.add(1);              // OK
    // Integer i = list.get(0); // 编译错误,只能当 Object 取
}

PECS 原则:Producer Extends, Consumer Super

9.3 类型擦除

泛型只在编译期生效,运行时会被擦除。List<String>和 List<Integer>在运行时都是 List。

List<String> l1 = new ArrayList<>();
List<Integer> l2 = new ArrayList<>();
System.out.println(l1.getClass() == l2.getClass()); // true

十、集合框架

10.1 整体结构

Collection
├── List(有序、可重复)
│   ├── ArrayList      —— 数组实现,查快增删慢(尾部例外)
│   └── LinkedList     —— 双向链表,增删快
├── Set(不重复)
│   ├── HashSet        —— 哈希表,无序
│   ├── LinkedHashSet  —— 哈希表+链表,保留插入顺序
│   └── TreeSet        —— 红黑树,自然排序
└── Queue / Deque
    ├── ArrayDeque     —— 双端队列,比 Stack 好用
    └── PriorityQueue  —— 优先级队列(堆)

Map(键值对,独立接口)
├── HashMap            —— 哈希表,常用
├── LinkedHashMap      —— 保留插入顺序
├── TreeMap            —— 红黑树,key 排序
└── ConcurrentHashMap  —— 线程安全的 HashMap

10.2 List

List<String> list = new ArrayList<>();
list.add("apple");
list.add(1, "banana");           // 指定位置插入
list.get(0);                      // "apple"
list.set(0, "orange");            // 替换
list.remove(0);                   // 按下标删除
list.remove("banana");            // 按元素删除
list.contains("apple");           // true
list.indexOf("apple");            // 下标,不存在返回-1
list.size();                      // 元素个数

// 遍历
for (int i = 0; i < list.size(); i++) { ... }
for (String s : list) { ... }
list.forEach(System.out::println);       // Java 8 Lambda
list.forEach((s) -> System.out.println(s));

// 截取
List<String> sub = list.subList(0, 3);   // 视图,改 sub 会影响原 list

10.3 Set

Set<Integer> set = new HashSet<>();
set.add(1);
set.add(2);
set.add(1);           // 重复,不会加进去
set.contains(1);      // true
set.remove(2);
set.size();

// 注意:HashSet 靠 hashCode + equals 判重,自定义类要重写这两个方法

10.4 Map

Map<String, Integer> map = new HashMap<>();
map.put("apple", 10);
map.get("apple");                      // 10
map.getOrDefault("banana", 0);         // 0(不存在返回默认值)
map.containsKey("apple");              // true
map.containsValue(10);                 // true

// 遍历
for (Map.Entry<String, Integer> entry : map.entrySet()) {
    System.out.println(entry.getKey() + " -> " + entry.getValue());
}
map.forEach((k, v) -> System.out.println(k + ": " + v));

// 只遍历 key 或 value
for (String key : map.keySet()) { ... }
for (Integer val : map.values()) { ... }

// 安全删除
map.keySet().removeIf(k -> k.startsWith("a"));

// 合并
map.merge("apple", 1, Integer::sum);   // 存在就加1,不存在就放1

10.5 集合工具类

// Collections
Collections.sort(list);
Collections.reverse(list);
Collections.shuffle(list);
Collections.max(list);
Collections.min(list);
Collections.frequency(list, "apple");
Collections.synchronizedList(list);        // 包装成线程安全

// Arrays → List
List<String> list = Arrays.asList("a", "b", "c");  // 不可变大小!
list.set(0, "x");   // OK
// list.add("d");    // 抛异常 UnsupportedOperationException

List<String> normalList = new ArrayList<>(Arrays.asList("a", "b", "c"));  // 这样才行

// List.of / Set.of / Map.of(Java 9+,不可变集合)
List<String> list = List.of("a", "b", "c");
Set<Integer> set = Set.of(1, 2, 3);
Map<String, Integer> map = Map.of("a", 1, "b", 2);

十一、文件 I/O

11.1 传统 IO(java.io)

// 读文本
try (BufferedReader reader = new BufferedReader(new FileReader("input.txt"))) {
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
}

// 写文本
try (BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {
    writer.write("Hello");
    writer.newLine();      // 写换行(跨平台)
    writer.write("World");
}

// 二进制读写
try (FileInputStream in = new FileInputStream("in.dat");
     FileOutputStream out = new FileOutputStream("out.dat")) {
    byte[] buffer = new byte[1024];
    int len;
    while ((len = in.read(buffer)) != -1) {
        out.write(buffer, 0, len);
    }
}

11.2 NIO(java.nio.file, Java 7+)

import java.nio.file.*;
import java.io.IOException;

// 读文本(一次全读)
String content = Files.readString(Path.of("file.txt"));

// 按行读
List<String> lines = Files.readAllLines(Path.of("file.txt"));

// 写文本
Files.writeString(Path.of("out.txt"), "Hello World!");

// 复制/移动/删除
Files.copy(Path.of("src"), Path.of("dest"), StandardCopyOption.REPLACE_EXISTING);
Files.move(Path.of("src"), Path.of("newName"));
Files.delete(Path.of("target"));              // 不存在抛异常
Files.deleteIfExists(Path.of("target"));

// 遍历目录
try (var stream = Files.list(Path.of("."))) {
    stream.filter(Files::isRegularFile)
          .forEach(System.out::println);
}

try (var walk = Files.walk(Path.of("."))) {   // 递归遍历
    walk.filter(p -> p.toString().endsWith(".java"))
        .forEach(System.out::println);
}

11.3 序列化

// 实现 Serializable 接口即可
public class User implements Serializable {
    private static final long serialVersionUID = 1L;  // 版本号
    private String name;
    private transient String password;  // transient 不序列化
}

// 序列化
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.dat"))) {
    oos.writeObject(user);
}

// 反序列化
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.dat"))) {
    User user = (User) ois.readObject();
}

十二、常用类速览

12.1 Object

所有类的祖宗:

obj.toString();             // getClass().getName() + "@" + hashCode()
obj.equals(otherObj);       // 默认 == 比较地址,通常需要重写
obj.hashCode();             // 重写 equals 必须重写 hashCode
obj.getClass();             // 获取运行时类信息(反射入口)
obj.clone();                // 浅拷贝(需实现 Cloneable)

12.2 String

// 判空
str == null || str.isEmpty();               // 长度=0
str == null || str.isBlank();               // Java 11+,只有空白也算空

// 匹配
"abc".matches("\\w+");                      // true
"abc".startsWith("a");                      // true
"abc".endsWith("c");                        // true

// 替换
"abcabc".replace("a", "x");                 // "xbcxbc"
"abcabc".replaceAll("\\w", "x");            // "xxxxxx" 正则

// 反转(String 本身没有,得绕一下)
new StringBuilder("abc").reverse().toString();  // "cba"

// 重复
"ha".repeat(3);                             // "hahaha"  Java 11+

12.3 Math

Math.abs(-5);           // 5
Math.max(3, 7);         // 7
Math.min(3, 7);         // 3
Math.pow(2, 10);        // 1024.0
Math.sqrt(16);          // 4.0
Math.random();           // [0.0, 1.0) 随机小数
Math.round(3.5);        // 4(四舍五入,.5 往偶数靠)
Math.ceil(3.1);         // 4.0(向上取整)
Math.floor(3.9);        // 3.0(向下取整)
Math.PI;                // 3.14159...

12.4 日期时间(java.time, Java 8+)

// 获取当前时间
LocalDate date = LocalDate.now();            // 2024-01-15
LocalTime time = LocalTime.now();            // 14:30:00
LocalDateTime dt = LocalDateTime.now();      // 日期+时间

// 创建指定时间
LocalDate.of(2024, 1, 15);
LocalTime.of(14, 30, 0);

// 格式化
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String s = dt.format(fmt);
LocalDateTime parsed = LocalDateTime.parse("2024-01-15 14:30:00", fmt);

// 运算(返回新对象,不改变原对象)
LocalDate tomorrow = date.plusDays(1);
LocalDate lastMonth = date.minusMonths(1);
boolean isAfter = date1.isAfter(date2);

// 时间差
Duration d = Duration.between(time1, time2);  // 时、分、秒
Period p = Period.between(date1, date2);       // 年、月、日

十三、枚举

public enum Season {
    SPRING, SUMMER, AUTUMN, WINTER
}

// 自带方法
Season s = Season.SPRING;
s.name();                    // "SPRING"
s.ordinal();                 // 0(声明顺序)
Season.values();             // [SPRING, SUMMER, AUTUMN, WINTER]
Season.valueOf("SUMMER");    // Season.SUMMER

// 带字段、构造、抽象方法(策略模式)
public enum Operation {
    PLUS("+")  { public double apply(double x, double y) { return x + y; } },
    MINUS("-") { public double apply(double x, double y) { return x - y; } };

    private final String symbol;
    Operation(String symbol) { this.symbol = symbol; }
    public abstract double apply(double x, double y);
}

// enum 实现单例(Effective Java 推荐)
public enum Config {
    INSTANCE;
    public void doSomething() { ... }
}

枚举专用集合(性能比 HashSet/HashMap 高):

EnumSet<Season> set = EnumSet.of(Season.SPRING, Season.SUMMER);
EnumMap<Season, String> map = new EnumMap<>(Season.class);
map.put(Season.SPRING, "春天");

十四、注解

14.1 内置常用注解

注解作用

@Override

标记方法重写,编译期校验

@Deprecated

标记已废弃(since、forRemoval)

@SuppressWarnings

压制编译器警告

@FunctionalInterface

标记函数式接口,编译期校验

@SafeVarargs

声明泛型可变参数安全

14.2 元注解(定义注解用的注解)



@Target

限制注解能用在哪(TYPE/METHOD/FIELD/PARAMETER 等)

@Retention

SOURCE(编译后消失)/ CLASS(class 中保留)/ RUNTIME(运行时可通过反射读取)

@Documented

是否写入 Javadoc

@Inherited

子类是否继承该注解

14.3 自定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String value() default "";   // 只有一个元素且叫 value 时,可省略 key
    int count() default 1;
    String[] tags() default {};
}

// 使用
@MyAnnotation(value = "hello", count = 3)
public void doSomething() {}

// 反射读取
Method m = obj.getClass().getMethod("doSomething");
if (m.isAnnotationPresent(MyAnnotation.class)) {
    MyAnnotation anno = m.getAnnotation(MyAnnotation.class);
    System.out.println(anno.value());
}

十五、反射

反射就是在运行时拿到类的信息并操作它,是框架的基石。

// 获取 Class 的三种方式
Class<?> clazz1 = Person.class;
Class<?> clazz2 = obj.getClass();
Class<?> clazz3 = Class.forName("com.example.Person");

// 创建实例
Constructor<?> ctor = clazz.getDeclaredConstructor(String.class, int.class);
Object obj = ctor.newInstance("张三", 20);

// 访问字段
Field field = clazz.getDeclaredField("name");
field.setAccessible(true);             // 私有字段要突破访问限制
String name = (String) field.get(obj);
field.set(obj, "李四");

// 调用方法
Method method = clazz.getDeclaredMethod("sayHello");
method.setAccessible(true);
method.invoke(obj);

// 获取注解
MyAnnotation anno = method.getAnnotation(MyAnnotation.class);

十六、动态代理

JDK 动态代理:运行时自动生成代理类,实现指定接口。所有方法调用会被转发到 InvocationHandler 的 invoke() 方法中处理。

import java.lang.reflect.*;

// 1. 定义接口
interface UserService {
    void addUser(String name);
}

// 2. 真实实现
class UserServiceImpl implements UserService {
    public void addUser(String name) {
        System.out.println("添加用户: " + name);
    }
}

// 3. 处理器(类似拦截器)
class LogHandler implements InvocationHandler {
    private final Object target;
    public LogHandler(Object target) { this.target = target; }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("[日志] 开始执行 " + method.getName());
        Object result = method.invoke(target, args);
        System.out.println("[日志] 执行完毕");
        return result;
    }
}

// 4. 使用
UserService target = new UserServiceImpl();
UserService proxy = (UserService) Proxy.newProxyInstance(
    target.getClass().getClassLoader(),
    new Class<?>[]{UserService.class},
    new LogHandler(target)
);
proxy.addUser("Alice");

限制:只能代理接口,因为生成的代理类已经继承 Proxy了,Java 不支持多继承。

十七、虚态一览

17.1 Lambda 表达式(Java 8+)

// Lambda 的演变
// 方式1:匿名内部类
Runnable r1 = new Runnable() {
    @Override public void run() { System.out.println("hi"); }
};

// 方式2:Lambda 表达式
Runnable r2 = () -> System.out.println("hi");

// 有参有返回值
Comparator<String> c = (a, b) -> a.compareTo(b);

// 多行用花括号
BiFunction<Integer, Integer, Integer> add = (a, b) -> {
    int result = a + b;
    return result;
};

17.2 方法引用

// 静态方法引用
Function<String, Integer> f1 = Integer::parseInt;

// 实例方法引用
String s = "hello";
Supplier<Integer> f2 = s::length;

// 构造器引用
Supplier<ArrayList<String>> f3 = ArrayList::new;

17.3 Stream API(Java 8+)

List<String> names = List.of("Alice", "Bob", "Charlie", "David");

// 中间操作(惰性)+ 终端操作(触发执行)
List<String> result = names.stream()
    .filter(n -> n.length() > 3)          // 过滤
    .map(String::toUpperCase)             // 转换
    .sorted()                             // 排序
    .distinct()                           // 去重
    .limit(2)                             // 截取前2个
    .collect(Collectors.toList());        // 收集

// 统计
long count = names.stream().filter(n -> n.startsWith("A")).count();

17.4 Optional(Java 8+)

避免 NullPointerException 的优雅方案:

Optional<String> opt = Optional.ofNullable(someString);

// 安全取值
String value = opt.orElse("默认值");
String value2 = opt.orElseGet(() -> computeDefault());

// 安全操作
opt.ifPresent(v -> System.out.println(v));
String upper = opt.map(String::toUpperCase).orElse("");

// 抛出异常
String value = opt.orElseThrow(() -> new IllegalStateException("不能为空"));

// 过滤
Optional<String> result = opt.filter(v -> v.length() > 3);

17.5 switch 表达式(Java 14+)

// 箭头语法(不需要 break)
String type = switch (day) {
    case 1, 2, 3, 4, 5 -> "工作日";
    case 6, 7 -> "周末";
    default -> "未知";
};

// yield 返回复杂值
int result = switch (status) {
    case "A" -> 1;
    case "B" -> {
        int n = compute();
        yield n * 2;    // yield 代替 return
    }
    default -> 0;
};

附录:新手常见坑

  1. == vs equals:==比引用地址,equals比值(String 重写了 equals,所以比较内容)

  2. Integer 缓存:-128 ~ 127 内的值用 == 比可能是 true(缓存),范围外一定是 false

  3. 空指针:调用方法前想想是不是 null,多用 Optional

  4. Arrays.asList() 返回的 List 不可增删,只是数组的一个视图

  5. 泛型擦除:List<String>和 List<Integer>在运行时是同一个类

  6. finally 不一定会执行:System.exit(0) 和 JVM 崩溃会跳过 finally

  7. 多态不再用父类私有方法:private 方法不能被重写,父类私用自己的版本

  8. switch 的类型限制:支持 int/String/枚举/char/byte/short,不支持 double/float/long/boolean

到这里,Java基础语法就介绍完了,该笔记定位是速查,碰到具体问题还是得翻书或看源码。Java 要多写代码,坑,自然就熟了。后续有新知识将更新……

如果在胜利前却步,往往只会拥抱失败;如果在困难时坚持,常常会获得新的成功。
0 不喜欢
说说我的看法 -
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
其他应用
公众号