全国计算机二级Java考试全部知识点总结【内附真题, 2026年9月最新】

这是之前备考时留下的 Java 二级笔记,后来又按教育考试院公开的二级 Java 考试大纲与样题补了一轮。考试环境的编辑器功能比较有限,和平时使用的 IntelliJ IDEA 差别很大,因此复习时除了看语法,还要练习在简单编辑器中定位编译错误。

Java 二级涉及的知识面比较宽,除了基础语法、面向对象、异常和线程,还保留了 AWT、Swing、Applet 等偏传统的 GUI 内容。操作题多为补空或修改既有代码,但仅背方法名并不稳,最好能看懂组件、容器和监听器之间的关系。

推荐题库:java.code2ji.cn(Java二级在线)

它的实用点是浏览器里可以直接运行 Java 小程序,并查看部分 GUI 题目的实际界面;手机端也能查看题面和填写代码。


Java 基础语法笔记

1. Java 基本概念

  • Java 是一种面向对象的编程语言,广泛应用于开发桌面应用、Web应用和Android应用。
  • Java 程序是由类(Class)组成的,每个程序必须有一个入口点,main 方法。

2. Java 程序结构

一个基本的 Java 程序结构如下:

public class HelloWorld {
    public static void main(String[] args) {
        // 这是输出语句
        System.out.println("Hello, World!");
    }
}

说明:

  • public class HelloWorld:定义一个类,类名通常与文件名相同。
  • public static void main(String[] args):main 方法是 Java 程序的入口点。
  • System.out.println:用于输出到控制台。

3. 基本数据类型

Java 有 8 种基本数据类型:

类型描述默认值
byte8位整数0
short16位整数0
int32位整数0
long64位整数0L
float单精度浮点数0.0f
double双精度浮点数0.0d
char单个字符‘\u0000’
boolean布尔值false

表中的默认值只适用于实例字段、静态字段和数组元素;局部变量在读取前必须显式赋值。Java 规范也没有规定 boolean 必须占几个字节。

4. 变量声明与赋值

声明和初始化变量:

int x = 10;         // 整型变量
double y = 3.14;    // 双精度浮点型变量
boolean isJava = true;  // 布尔型变量
char grade = 'A';   // 字符型变量

常见操作:

x = 20;             // 变量赋值
int sum = x + 10;   // 变量计算

5. 控制结构

条件语句

Java 使用 if, else if, 和 else 来进行条件判断。

int age = 18;
if (age >= 18) {
    System.out.println("You are an adult.");
} else {
    System.out.println("You are a minor.");
}

循环语句

Java 提供了 forwhiledo-while 三种循环结构。

for 循环:

for (int i = 0; i < 5; i++) {
    System.out.println("i = " + i);
}

while 循环:

int j = 0;
while (j < 5) {
    System.out.println("j = " + j);
    j++;
}

do-while 循环:

int k = 0;
do {
    System.out.println("k = " + k);
    k++;
} while (k < 5);

6. 数组

一维数组

int[] numbers = {1, 2, 3, 4, 5};
System.out.println(numbers[0]);  // 输出 1

二维数组

int[][] matrix = {{1, 2, 3}, {4, 5, 6}};
System.out.println(matrix[1][2]);  // 输出 6

真题实战:5×5 上三角矩阵(题目来源:java.code2ji.cn

来看这道经典的数组操作题:

Java二级5×5矩阵程序题题面

题目要求:构造一个 5×5 的上三角矩阵并输出。

public class Main {
   public static void main(String args[]) { 
      int a[][] = new int[5][5];  // 声明5×5二维数组
      int i, j, k = 1;
      for(i = 0; i < 5; i++)
         for(j = 0; j < 5; j++)
            if((i + j) < 5) {     // 上三角条件
               a[i][j] = k;
               k++;               // 递增
               if (k > 9) k = 1;  // 大于9重置为1
            } else
               a[i][j] = 0;       // 下三角设为0
      for(i = 0; i < 5; i++) { 
         for(j = 0; j < 5; j++)
            System.out.print(a[i][j] + "   ");
         System.out.println();    // 换行
      }
   }
}

解题思路与考点解析:

这道题考查二维数组操作和上三角矩阵的构造,需要理解数组索引与矩阵位置的关系。

  1. 二维数组声明int a[][] = new int[5][5] 创建 5×5 数组;
  2. 条件判断(i + j) < 5 判断是否在上三角区域;
  3. 循环赋值k 值循环使用 1-9,超过 9 重置为 1;
  4. 记忆技巧:二维数组 a[行][列],先行后列;副对角线上三角条件为 行索引 + 列索引 < 总阶数

7. 方法(函数)

方法声明和调用:

public class Main {
    public static void main(String[] args) {
        greet("Alice");
    }

    public static void greet(String name) {
        System.out.println("Hello, " + name);
    }
}

8. 面向对象

类与对象

class Person {
    String name;
    int age;

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

    public void greet() {
        System.out.println("Hello, my name is " + name + " and I am " + age + " years old.");
    }
}

public class Main {
    public static void main(String[] args) {
        Person p = new Person("Alice", 30);
        p.greet();
    }
}

继承与多态

class Animal {
    public void sound() {
        System.out.println("Animal makes a sound.");
    }
}

class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("Dog barks.");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal a = new Dog();
        a.sound();  // 输出: Dog barks. (多态调用)
    }
}

重载、重写、抽象类与接口速查

  • 重载(overload):发生在同一个类中,方法名相同,参数个数、类型或顺序不同;不能只靠返回类型区分。
  • 重写(override):子类重新实现父类的实例方法,方法签名一致,访问权限不能缩小,可使用 @Override 检查。
  • 抽象类:用 abstract class 声明,可以有字段、构造方法、普通方法和抽象方法,不能直接实例化。
  • 接口:字段隐式为 public static final;没有方法体的普通接口方法隐式为 public abstract。一个类只能直接继承一个父类,但可以实现多个接口。

访问范围从小到大可记为:private → 默认包访问 → protectedpublicstatic 成员属于类,静态方法中不能直接使用 this 或访问实例字段。

9. 常见类库

// String
String greeting = "Hello, World!";
System.out.println(greeting.length());
System.out.println(greeting.toUpperCase());

// ArrayList
import java.util.ArrayList;
ArrayList<String> list = new ArrayList<>();
list.add("Apple");
System.out.println(list.get(0));

// Scanner 输入
import java.util.Scanner;
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();

从下面开始进入更容易丢分的部分。Java 二级不只考基础语法,还会涉及异常、I/O、线程和 GUI,代码一长就更考验阅读顺序。


进阶考点:异常、IO、多线程与 GUI

1. 异常处理

public static void main(String[] args) {
    test(1, 0);   // 当 b 为 0 的时候,还能正常运行吗?
}

private static int test(int a, int b) {
    return a / b; // 没有任何的判断而是直接做计算
}

结果会报错:

报错截图

考试环境如果允许复制文本,调试时可以先从报错信息里复制异常类名再搜索代码位置;不过 ArithmeticExceptionNullPointerExceptionArrayIndexOutOfBoundsExceptionIOException 这些高频类型仍然值得直接认出来。

异常的类型

Java 中可抛出的对象都继承自 Throwable。它下面主要分为 ErrorException;常见运行时异常继承自 RuntimeException,受检异常则需要捕获或在方法签名中声明抛出。

如空指针异常:

public static void main(String[] args) {
    Object object = null;
    object.toString(); // 运行时抛出 NullPointerException
}

空指针异常截图

抛出异常

当传入错误参数导致无法运行,我们可以手动抛出异常:

public static int test(int a, int b) {
    if (b == 0)
        throw new IllegalArgumentException("除数不能为0");
    return a / b;
}

当出现异常时:

异常调用栈追踪

程序会终止并打印栈追踪信息。实际上方法之间的调用是有层级关系的,位于最上面的就是发生异常的最核心代码行。

异常的捕获与处理

简单来说就是程序在遇到异常的时候会不知道怎么办,一般情况下会自动终止。然而你作为伟大的程序员早就料到了这一切,并且要求程序在遇到这个问题的时候不用停止,按照你说的继续做下去:

public static void main(String[] args) {
    try {
        Object object = null;
        object.toString();
    } catch (NullPointerException e) {
        System.out.println("捕获到了空指针异常!");
    }
    System.out.println("程序继续正常运行!");
}

异常捕获效果

多重异常捕获注意顺序:子类在前,父类在后

try {
    // 可能出错的代码
} catch (NullPointerException e) {
    // 处理空指针
} catch (IndexOutOfBoundsException e) {
    // 处理数组越界
} catch (Exception e) {
    // 处理其他异常
} finally {
    System.out.println("无论是否出现异常,都会在最后执行!");
}

2. Java I/O 输入输出流

I/O 简而言之就是输入输出。

文件字节流

使用 FileInputStream 获取输入流:

// JDK 1.7 try-with-resources 语法,自动释放资源
try (FileInputStream inputStream = new FileInputStream("test.txt")) {
    int tmp;
    while ((tmp = inputStream.read()) != -1) { // 循环按字节读取,-1 表示文件结束
        System.out.print((char)tmp);
    }
} catch (IOException e) {
    e.printStackTrace();
}

小文件演示中也能按当前可读字节数准备缓冲区:

try (FileInputStream inputStream = new FileInputStream("test.txt")) {
    byte[] bytes = new byte[inputStream.available()];
    inputStream.read(bytes);
    System.out.println(new String(bytes));
} catch (IOException e) {
    e.printStackTrace();
}

available() 不是“文件总长度”的通用接口,只表示当前无需阻塞即可读取的字节数。正式处理文件更稳妥的写法是循环调用 read(buffer),并以返回值 -1 判断结束。

文件输出流与文件拷贝:

try (FileOutputStream outputStream = new FileOutputStream("output.txt");
     FileInputStream inputStream = new FileInputStream("test.txt")) {
    byte[] bytes = new byte[10];
    int tmp;
    while ((tmp = inputStream.read(bytes)) != -1) {
        outputStream.write(bytes, 0, tmp);
    }
} catch (IOException e) {
    e.printStackTrace();
}

对格式的疑惑请见:

IO流格式说明


真题实战:文件数据流读写(题目来源:java.code2ji.cn

import java.io.*;

public class Main {
  public static void main(String[] args) {
    char[] charArray = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'};
    char c;
    try {
        // 创建数据输出流,写入文件
        DataOutputStream out = new DataOutputStream(new FileOutputStream("test.txt"));
        for(int i = 0; i < charArray.length; i++) {
           out.writeChar(charArray[i]);  // 写入字符
        }
        out.close();
        
        // 创建数据输入流,从文件读取
        DataInputStream in = new DataInputStream(new FileInputStream("test.txt"));
        while(in.available() != 0) {
           c = in.readChar();           // 读取字符
           System.out.print(c + " ");
        }
        System.out.println();
        in.close();
    } catch(IOException e) {
        e.printStackTrace();
    }
  }
}

这道题为了配合 DataInputStream 的演示使用了 available()。实际工程中不应把它理解为通用的“剩余文件长度”;处理未知长度的数据时,应根据读取方法的返回值或捕获 EOF 来判断结束。


3. 多线程编程

在了解多线程之前,回顾一下进程概念:进程是程序执行的实体(比如我们运行 QQ、浏览器、LOL、网易云音乐等),都有自己的内存空间。

进程示意图

但是如果我希望两个任务同时进行,进程之间通信太麻烦,上下文切换非常耗时。

多线程诞生

后来线程横空出世,一个进程可以有多个线程,各个线程之间共享程序的内存空间。

线程的创建和启动

通过 Lambda 或匿名内部类实现 Runnable

匿名内部类
内部类结构
Lambda简化

双线程并发交替执行实例:

public class Main {
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 20; i++) System.out.println("一号线程: " + i);
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 20; i++) System.out.println("二号线程: " + i);
        });
        t1.start(); // 必须调用 start(),不能调用 run()!
        t2.start();
    }
}

run与start区别

线程锁与 synchronized 同步

多线程下变量存储在主内存中,每个线程有自己的工作内存:

内存模型
缓存一致性

如果同时写入共享变量就会导致数据错乱:

数据错乱现象

使用 synchronized 关键字创建同步锁:

private static int value = 0;

public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(() -> {
        for (int i = 0; i < 10000; i++) {
            synchronized (Main.class) {
                value++;
            }
        }
    });
    Thread t2 = new Thread(() -> {
        for (int i = 0; i < 10000; i++) {
            synchronized (Main.class) {
                value++;
            }
        }
    });
    t1.start();
    t2.start();
    t1.join();
    t2.join();
    System.out.println("最终结果: " + value); // 两个线程结束后输出 20000
}

这里必须等待两个工作线程结束。Thread.sleep(1000) 只能让当前线程暂停一段时间,并不能保证另外两个线程恰好已经执行完成;join() 才是在等待目标线程终止。

死锁现象

当线程相互持有对方需要的锁又不释放时产生死锁:

死锁示意图
死锁代码演示

ThreadLocal 线程本地变量

不同的线程访问到 ThreadLocal 对象时,都只能获取到当前线程所属的变量:

ThreadLocal模型


4. GUI 程序开发(AWT 与 Swing)

这部分不必死记所有组件,先抓住“创建组件 → 设置属性 → 加入容器 → 绑定事件”这条主线。

AWT 组件与窗口

AWT(Abstract Window Toolkit)是 Java 提供的抽象窗口工具包。

操作系统窗口
(woc,原)

创建基本窗口与事件监听器:

import java.awt.*;
import java.awt.event.*;

public class Main {
    public static void main(String[] args) {
        Frame frame = new Frame("AWT窗口");
        frame.setSize(400, 250);
        frame.setLayout(null); // 绝对定位

        // 标签
        Label label = new Label("用户名:");
        label.setBounds(30, 50, 60, 25);
        frame.add(label);

        // 文本框
        TextField field = new TextField();
        field.setBounds(100, 50, 150, 25);
        frame.add(field);

        // 按钮与点击监听
        Button button = new Button("点击登录");
        button.setBounds(100, 90, 80, 30);
        button.addActionListener(e -> System.out.println("输入的内容是: " + field.getText()));
        frame.add(button);

        // 窗口关闭监听
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                frame.dispose();
                System.exit(0);
            }
        });

        frame.setVisible(true);
    }
}

组件布局
文本框与按钮
菜单栏展示
菜单项点击


5. Swing 实战大题:模拟 QQ 登录界面

这是一道非常综合的机考真题:

Java二级QQ登录界面程序题题面

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Main extends JFrame {
    private JTextField username;
    private JPasswordField password;
    private JLabel jl3;
    private JLabel jl4;
    private JButton bu1, bu2, bu3;
    private JCheckBox jc1, jc2;
    private JComboBox<String> jcb;

    public Main() {
        this.setTitle("QQ2025正式版");
        init();
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLayout(null);
        this.setBounds(0, 0, 355, 265);
        this.setResizable(false);
        this.setLocationRelativeTo(null);
        this.setVisible(true);
    }

    public void init() {
        Container con = this.getContentPane();

        username = new JTextField();
        username.setBounds(50, 50, 150, 20);

        jl3 = new JLabel("注册账号");
        jl3.setBounds(210, 50, 70, 20);

        password = new JPasswordField();
        password.setBounds(50, 80, 150, 20);

        jl4 = new JLabel("找回密码");
        jl4.setBounds(210, 80, 70, 20);

        jc1 = new JCheckBox("记住密码");
        jc1.setBounds(125, 135, 80, 15);

        jc2 = new JCheckBox("自动登录");
        jc2.setBounds(215, 135, 80, 15);

        jcb = new JComboBox<>();
        jcb.addItem("在线");
        jcb.addItem("隐身");
        jcb.addItem("离开");
        jcb.setBounds(40, 135, 55, 20);

        bu1 = new JButton("登录");
        bu1.setBounds(250, 200, 65, 20);
        bu1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showConfirmDialog(null, "您输入的用户名是 " + username.getText());
            }
        });

        bu2 = new JButton("多账号");
        bu2.setBounds(25, 200, 75, 20);

        bu3 = new JButton("设置");
        bu3.setBounds(140, 200, 65, 20);

        con.add(username); con.add(password);
        con.add(jl3); con.add(jl4);
        con.add(jc1); con.add(jc2);
        con.add(jcb);
        con.add(bu1); con.add(bu2); con.add(bu3);
    }

    public static void main(String[] args) {
        new Main();
    }
}

解题思路与考点总结:

  1. GUI 编程三步法:创建组件 → \rightarrow 设置属性/坐标(setBounds → \rightarrow 添加到容器(con.add);
  2. 事件监听button.addActionListener(e -> ...)
  3. 密码框组件:使用 JPasswordField 自动隐藏输入明文。

结语

差不多也就这些内容(其实真不少)。

题库平台最后还是拿出来夸一下:java.code2ji.cn

能在线跑代码、查看部分 GUI 题的界面,手机也能打开题面,用来零散复习很方便。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值