← 回期末复习

Java 详细版(给会 C++ / Python 的你)

你已经会编程,所以这门课不是「学编程」,是学 Java 的规矩。
每节都写:Java 怎么做 → 和 C++/Python 差在哪 → 考试怎么考。
配合《java-知识点》(章节索引)和《形象版-java》(比喻)一起用。

0. 先建立三个直觉

C++PythonJava
运行方式编译成机器码解释执行编译成字节码,JVM 解释/JIT
内存手动 new/delete引用计数 + GC自动 GC(你不用管)
类型强类型、可隐式转换多动态类型强类型、静态检查,转换要显式
一切皆对象?否是否(8 种基本类型不是对象,其余都是)
多继承支持类多继承支持不支持,用接口多实现

一句话:Java = 去掉指针和手动内存管理的 C++ + 强制静态类型的 Python。


第 1 章 Java 入门

开发三件事


Hello.java  --javac-->  Hello.class  --java-->  运行
(源码)                (字节码)              (JVM 执行)

代码骨架(和 C++ 的 main 对比)


public class Hello {                 // 文件名必须 Hello.java
    public static void main(String[] args) {
        System.out.println("hi");    // C++: cout << "hi" << endl;
    }
}

第 2 章 基本数据类型与数组

2.1 八种基本类型(C++ 对照)

Java字节范围/说明C++ 对应
byte1-128~127char / int8_t
short2±3.2万short
int4±21亿int
long8后面要加 Llong long
float4要加 ffloat
double8默认小数类型double
char2Unicode,不是 ASCIIwchar_t
boolean1只有 true/falsebool

⚠️ Java 没有无符号类型(没有 unsigned);char 是 2 字节,能存中文。


int a = 10;
long b = 100L;        // 不加 L 也能过,但超范围会错
float f = 3.14f;      // 不加 f 编译报错
char c = '中';        // 合法
boolean ok = true;    // 不能写 1

和 C++ 的关键差异:C++ 里 if (1) 合法,Java 里 if 只接受 boolean。

2.2 类型转换


int i = 100;
long l = i;          // 自动(小→大)
int j = (int) l;     // 强制(大→小)

byte b = 10;
b = b + 1;           // ❌ 编译错误:b+1 变成 int
b = (byte)(b + 1);   // ✅
b += 1;              // ✅ 复合赋值会自动强转

⚠️ 考点:byte b = 10; b = b + 1; 为什么错 → 整数运算自动提升为 int。

2.3 输入输出


import java.util.Scanner;
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
double d = sc.nextDouble();
String s = sc.next();        // 遇到空白停
String line = sc.nextLine(); // 读一整行(前面有 nextInt 时要注意吃掉换行)

System.out.print("x");
System.out.println("换行");
System.out.printf("%d %.2f%n", n, d);   // 类似 C 的 printf

⚠️ 经典坑:nextInt() 后紧跟 nextLine() 会读到空串,要先 sc.nextLine() 吃掉回车。

2.4 数组


int[] a = new int[5];            // C++: int a[5];
int[] b = {1, 2, 3};             // 静态初始化
int[][] c = new int[3][4];       // 二维
System.out.println(a.length);    // 属性!不是 a.length()(String 才是 length())

int[] a = {5, 2, 8};
Arrays.sort(a);                    // 升序
System.out.println(Arrays.toString(a));  // [2, 5, 8]

第 3 章 运算符、表达式和语句

大部分和 C++ 一样,重点差异:


int i = 5;
int x = i++;   // x=5, i=6
int y = ++i;   // i=7, y=7

System.out.println(7 / 2);      // 3(整除)
System.out.println(7 % 3);      // 1
System.out.println(-7 % 3);     // -1(负数取模结果为负)

boolean r = (a > 1) && (b < 2); // 短路

switch(支持 byte/short/char/int/String/枚举):


switch (day) {
    case 1: System.out.println("周一"); break;   // 忘了 break 会穿透
    default: System.out.println("其他");
}

手写排序(考试常考,必须会):


// 冒泡排序
for (int i = 0; i < n - 1; i++)
    for (int j = 0; j < n - 1 - i; j++)
        if (a[j] > a[j + 1]) {
            int t = a[j]; a[j] = a[j + 1]; a[j + 1] = t;
        }

// 选择排序
for (int i = 0; i < n - 1; i++) {
    int k = i;
    for (int j = i + 1; j < n; j++) if (a[j] < a[k]) k = j;
    int t = a[i]; a[i] = a[k]; a[k] = t;
}

第 4 章 类与对象

4.1 类的基本结构


public class Student {
    private String name;      // 成员变量(默认值 null)
    private int age;          // 默认 0

    public Student() { }                       // 无参构造
    public Student(String name, int age) {     // 有参构造
        this.name = name;                      // this 区分同名
        this.age = age;
    }

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

    public String toString() {                 // 重写,等价 C++ 的 operator<<
        return "Student(" + name + "," + age + ")";
    }
}

和 C++ 的差异:

4.2 构造方法

⚠️ 考点:构造方法能不能被重写?→ 不能(它不属于继承的方法,名字也不是自己的)。

4.3 对象引用(最容易错)


Student s1 = new Student("张三", 18);
Student s2 = s1;             // 不是复制!两个引用指向同一对象
s2.setAge(20);
System.out.println(s1.getAge());  // 20

4.4 成员变量 vs 局部变量(必考简答)

成员变量局部变量
位置类里、方法外方法内/参数
默认值有(0/null/false)无,必须初始化
内存堆(对象里)栈
生命周期跟对象跟方法调用

4.5 static


public class Counter {
    static int count = 0;        // 所有对象共用
    static { count = 0; }        // 静态代码块,类加载时执行一次
    static int get() { return count; }
    int normal() { return count; }   // 普通方法能访问静态
    // static void f() { normal(); }  ❌ 静态不能访问非静态
}

⚠️ 为什么静态方法不能访问非静态成员?→ 静态属于类,加载时可能还没有对象。

4.6 封装与访问权限


private   int a;   // 只有本类
          int b;   // 同包
protected int c;   // 同包 + 子类
public    int d;   // 所有

封装 = 成员变量 private + 提供 get/set。


第 5 章 子类与继承


class Animal {
    protected String name;
    public void speak() { System.out.println("..."); }
}

class Dog extends Animal {
    @Override
    public void speak() { System.out.println("汪汪"); }   // 重写
    public void bark() { super.speak(); speak(); }        // super 调父类
}

重写 vs 重载(必考)

重写 Override重载 Overload
位置子类 vs 父类同一个类
方法名相同相同
参数列表必须相同必须不同
返回值相同或兼容无关
权限不能更小无关

(形象记忆:重写是"改内容",重载是"加花样"。)

final

上转型对象与多态


Animal a = new Dog();   // 上转型
a.speak();              // 汪汪(看实际对象)
// a.bark();            ❌ 编译期按 Animal 检查,没有 bark

Dog d = (Dog) a;        // 下转型,要强转
if (a instanceof Dog) { Dog d2 = (Dog) a; }   // 先用 instanceof 判断

⚠️ 规则:成员方法看右边(运行时类型),成员变量看左边(编译时类型)。


class A { int x = 1; int get() { return 1; } }
class B extends A { int x = 2; int get() { return 2; } }
A a = new B();
System.out.println(a.x);      // 1(变量看左边)
System.out.println(a.get());  // 2(方法看右边)

第 6 章 接口与实现


interface Fly {
    int MAX = 100;               // 默认 public static final
    void fly();                  // 默认 public abstract
}

abstract class Bird {
    abstract void eat();         // 抽象方法
    void sleep() { }             // 普通方法
}

class Sparrow extends Bird implements Fly {
    void eat() { }
    public void fly() { }
}

抽象类 vs 接口(必考 4 条)

抽象类接口
关键字abstract classinterface
继承单继承多实现
构造方法有没有
成员变量/普通方法/抽象方法常量 + 抽象方法(JDK8+ 可有 default/static)

共同点:都不能 new,都用于多态。

接口回调(常考代码题)


interface Callback { void done(String result); }

class Worker {
    void work(Callback cb) { cb.done("完成"); }
}

new Worker().work(new Callback() {          // 匿名内部类
    public void done(String r) { System.out.println(r); }
});

第 7 章 内部类与异常

内部类


class Outer {
    int x = 1;
    class Inner { void f() { System.out.println(x); } }   // 成员内部类
    static class SInner { }                               // 静态内部类
    void g() { class Local { } }                          // 局部内部类
}

匿名内部类最常考(上面接口回调的例子)。

异常体系


Throwable
 ├── Error(VirtualMachineError 等,程序管不了)
 └── Exception
      ├── RuntimeException(运行时:空指针、越界、类型转换)
      └── 其他(编译时异常:IO、SQL,必须处理)

try {
    int x = 10 / 0;
} catch (ArithmeticException e) {
    System.out.println("除零:" + e.getMessage());
} finally {
    System.out.println("一定执行");       // 关资源写这里
}

⚠️ 执行顺序题:try 里 return 了,finally 还会执行吗?→ 会(在 return 之前执行),除非 System.exit(0)。


第 8 章 常用实用类

String(重点)


String s = "hello";
s.length();            // 5(方法,带括号)
s.charAt(1);           // 'e'
s.substring(1, 4);     // "ell"(含头不含尾)
s.indexOf("l");        // 2
s.replace("l", "L");   // "heLLo"(返回新串)
s.split(",");          // 按逗号切
s.trim();              // 去首尾空格
s.toUpperCase();
Integer.parseInt("123");       // 字符串转 int
String.valueOf(123);           // 基本类型转字符串

⚠️ String 不可变:s = s + "x" 每次都新建对象,循环里别这么写。


String a = "abc";
String b = "abc";
String c = new String("abc");
a == b;        // true(常量池同一个对象)
a == c;        // false(new 出来是新的)
a.equals(c);   // true(比内容)

StringBuffer / StringBuilder


StringBuilder sb = new StringBuilder();
sb.append("a").append(1);     // 链式
sb.reverse();
sb.toString();

包装类与自动装箱


Integer i = 100;         // 自动装箱
int j = i;               // 自动拆箱
Integer.parseInt("42");

Integer a = 127, b = 127;
System.out.println(a == b);   // true(缓存 -128~127)
Integer c = 128, d = 128;
System.out.println(c == d);   // false(超范围是新对象)

日期


Date now = new Date();
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(fmt.format(now));       // 格式化
Date d = fmt.parse("2025-01-01 00:00:00"); // 解析

Calendar cal = Calendar.getInstance();
cal.set(2025, 0, 1);
cal.add(Calendar.DAY_OF_MONTH, 7);

⚠️ 月份从 0 开始(0=一月)。


第 10 章 IO 流


字节流:InputStream / OutputStream   (什么都能读写)
字符流:Reader / Writer              (只能文本,能按行)

// 写文件(字符流 + 缓冲)
try (BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"))) {
    bw.write("hello");
    bw.newLine();
}   // try-with-resources 自动关闭

// 读文件按行
try (BufferedReader br = new BufferedReader(new FileReader("a.txt"))) {
    String line;
    while ((line = br.readLine()) != null) System.out.println(line);
}

// 复制文件(字节流)
try (FileInputStream in = new FileInputStream("a.jpg");
     FileOutputStream out = new FileOutputStream("b.jpg")) {
    byte[] buf = new byte[1024];
    int n;
    while ((n = in.read(buf)) != -1) out.write(buf, 0, n);
}

⚠️ 对比 Python:with open(...) as f: 就是 Java 的 try-with-resources。


第 12 章 多线程


// 方式一:实现 Runnable(推荐)
Thread t = new Thread(() -> System.out.println("跑"));
t.start();

// 方式二:继承 Thread
class MyThread extends Thread {
    public void run() { System.out.println("跑"); }
}
new MyThread().start();

同步:


class Ticket {
    private int n = 10;
    public synchronized void sell() {   // 方法锁
        if (n > 0) n--;
    }
    public void sell2() {
        synchronized (this) { if (n > 0) n--; }   // 代码块锁
    }
}

死锁四条件:互斥、请求并保持、不可剥夺、循环等待。


第 15 章 集合与栈队列(重点)


import java.util.*;

List<String> list = new ArrayList<>();
list.add("a"); list.get(0); list.size(); list.remove(0);

Map<String, Integer> map = new HashMap<>();
map.put("k", 1); map.get("k"); map.containsKey("k");
for (Map.Entry<String, Integer> e : map.entrySet()) {
    System.out.println(e.getKey() + "=" + e.getValue());
}

Set<Integer> set = new HashSet<>();
set.add(1); set.contains(1);

Stack<Integer> st = new Stack<>();
st.push(1); st.peek(); st.pop(); st.isEmpty();

Queue<Integer> q = new LinkedList<>();
q.offer(1); q.peek(); q.poll(); q.isEmpty();

和 C++ STL 对照:

JavaC++说明
ArrayListvector动态数组
LinkedListlist双向链表
HashMapunordered_map哈希表
TreeMapmap红黑树,有序
HashSetunordered_set去重
Stackstack后进先出
Queue / Dequequeue / deque先进先出
PriorityQueuepriority_queue堆

排序:


List<Integer> a = new ArrayList<>(List.of(3, 1, 2));
Collections.sort(a);                       // 升序
a.sort((x, y) -> y - x);                   // 降序(Comparator)

⚠️ List 不能直接存 int(要 Integer),自动装箱。


高频代码题模板(背下来)


// 1. 学生类
class Student {
    private String name; private int score;
    public Student(String name, int score) { this.name = name; this.score = score; }
    public String getName() { return name; }
    public int getScore() { return score; }
    public String toString() { return name + ":" + score; }
}

// 2. 冒泡排序
// 3. 求最大值
// 4. 字符串反转
StringBuilder sb = new StringBuilder(s).reverse();

// 5. 统计字符出现次数
Map<Character, Integer> m = new HashMap<>();
for (char c : s.toCharArray()) m.put(c, m.getOrDefault(c, 0) + 1);

// 6. 文件复制(见第 10 章)
// 7. 多线程卖票(见第 12 章)

考前自测清单