课后作业



Foo obj1 = new Foo(); // 这里调用了无参构造方法
必须传入一个 int 类型的参数来创建 Foo 对象
总结出“静态初始化块的执行顺序”。
在 Java 中,静态初始化块(static { ... })的执行顺序遵循以下核心规则:
静态初始化块执行顺序总结:
- 类加载时执行,且只执行一次
当类被首次主动使用时(如:创建对象、访问静态成员、反射等),JVM 会加载该类。
静态初始化块在类加载阶段执行,只执行一次。 - 父类优先于子类
如果存在继承关系,父类的静态初始化块先于子类的静态初始化块执行。 - 同类中按代码顺序执行
同一个类中,如果有多个静态初始化块,按它们在代码中出现的顺序依次执行。

package code;
import java.awt.;
import java.awt.event.;
import java.io.;
import java.nio.file.;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.;
import java.util.List;
import java.util.concurrent.;
import javax.swing.*;
/**
-
四则运算练习器 —— 单文件 Eclipse 直接运行
-
文件名:MathPracticeGUI4.java
-
错题无任何标记,仅列出题目、你的答案、正确答案
*/
public class MathPracticeGUI4 extends JFrame {
private static final int QUESTION_CNT = 20; // 题量(4 的倍数)
private static final int TIME_SECONDS = 120; // 倒计时
private static final Path SAVE_DIR = Paths.get("d:/math");private final CardLayout card = new CardLayout();
private final JPanel mainPanel = new JPanel(card);/* 面板 */
private final MenuPanel menuPanel = new MenuPanel();
private final ExamPanel examPanel = new ExamPanel();
private final ResultPanel resultPanel = new ResultPanel();/* 全局数据 */
private ListcurExercises;
private int curCorrect;
private boolean curTimeout;
private ListcurWrongIdx = new ArrayList<>();
private final Listhistory = new ArrayList<>(); public MathPracticeGUI4() {
super("四则运算练习器(每行4题)");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(800, 600);
setLocationRelativeTo(null);mainPanel.add(menuPanel, "menu"); mainPanel.add(examPanel, "exam"); mainPanel.add(resultPanel, "result"); add(mainPanel); card.show(mainPanel, "menu");}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
try {
if (!Files.exists(SAVE_DIR)) Files.createDirectories(SAVE_DIR);
} catch (IOException e) {
e.printStackTrace();
}
new MathPracticeGUI4().setVisible(true);
});
}/* 菜单面板 */
private class MenuPanel extends JPanel {
MenuPanel() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);JButton btnNew = new JButton("开始新一套练习"); JButton btnWrong = new JButton("错题重练"); JButton btnExit = new JButton("退出"); gbc.gridx = 0; gbc.gridy = 0; add(btnNew, gbc); gbc.gridy++; add(btnWrong, gbc); gbc.gridy++; add(btnExit, gbc); btnNew.addActionListener(e -> startNew(false)); btnWrong.addActionListener(e -> { List<Exercise> wrong = collectWrong(); if (wrong.isEmpty()) { JOptionPane.showMessageDialog(this, "暂无错题!"); return; } startNew(true); }); btnExit.addActionListener(e -> System.exit(0)); }}
/* 答题面板 /
private class ExamPanel extends JPanel {
private final JLabel lblTimer = new JLabel("剩余时间:120 s");
private final JProgressBar bar = new JProgressBar(0, TIME_SECONDS);
private final JPanel centerPanel = new JPanel(new GridLayout(0, 8, 10, 10)); // 4题2
private final ListanswerFields = new ArrayList<>();
private ScheduledExecutorService timerService;
private int remain;ExamPanel() { setLayout(new BorderLayout(10, 10)); setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); /* 顶部倒计时 */ JPanel top = new JPanel(new BorderLayout()); top.add(lblTimer, BorderLayout.WEST); top.add(bar, BorderLayout.CENTER); add(top, BorderLayout.NORTH); /* 中部题目区 */ JScrollPane scroll = new JScrollPane(centerPanel); add(scroll, BorderLayout.CENTER); /* 底部提交按钮 */ JButton btnSubmit = new JButton("提交"); btnSubmit.setFont(new Font("微软雅黑", Font.BOLD, 18)); btnSubmit.addActionListener(e -> finishExam(false)); JPanel south = new JPanel(); south.add(btnSubmit); add(south, BorderLayout.SOUTH); } void startExam(List<Exercise> list) { curExercises = list; remain = TIME_SECONDS; bar.setValue(TIME_SECONDS); lblTimer.setText("剩余时间:" + remain + " s"); answerFields.clear(); centerPanel.removeAll(); /* 每行4题:标签 + 输入框 */ for (int i = 0; i < list.size(); i++) { Exercise e = list.get(i); JLabel lbl = new JLabel((i + 1) + ". " + e.getText() + " = "); lbl.setFont(new Font("微软雅黑", Font.PLAIN, 18)); JTextField txt = new JTextField(4); txt.setFont(new Font("微软雅黑", Font.PLAIN, 18)); answerFields.add(txt); centerPanel.add(lbl); centerPanel.add(txt); } revalidate(); repaint(); card.show(mainPanel, "exam"); /* 倒计时线程 */ timerService = Executors.newSingleThreadScheduledExecutor(); timerService.scheduleAtFixedRate(() -> { remain--; EventQueue.invokeLater(() -> { bar.setValue(remain); lblTimer.setText("剩余时间:" + remain + " s"); }); if (remain <= 0) { timerService.shutdownNow(); EventQueue.invokeLater(() -> finishExam(true)); } }, 1, 1, TimeUnit.SECONDS); } private void finishExam(boolean timeout) { if (timerService != null && !timerService.isShutdown()) timerService.shutdownNow(); int correct = 0; List<Integer> wrongIdx = new ArrayList<>(); for (int i = 0; i < curExercises.size(); i++) { try { int ans = Integer.parseInt(answerFields.get(i).getText().trim()); if (ans == curExercises.get(i).getResult()) correct++; else wrongIdx.add(i); } catch (NumberFormatException ex) { wrongIdx.add(i); } } curCorrect = correct; curTimeout = timeout; curWrongIdx = wrongIdx; /* 保存文件 */ try { new ExerciseSet(curExercises).exportToFile(SAVE_DIR); } catch (IOException ex) { ex.printStackTrace(); } /* 弹出详细结算窗(无标记) */ showDetailDialog(); } /* 逐题结算:题目、你的答案、正确答案(无标记) */ private void showDetailDialog() { JTextArea area = new JTextArea(15, 40); area.setEditable(false); area.setFont(new Font("微软雅黑", Font.PLAIN, 16)); StringBuilder sb = new StringBuilder(); sb.append("详细结算\n"); for (int i = 0; i < curExercises.size(); i++) { Exercise e = curExercises.get(i); String user; try { user = answerFields.get(i).getText().trim(); } catch (Exception ex) { user = ""; } sb.append(String.format("%2d. %-10s = %4s (正确答案:%d)%n", i + 1, e.getText(), user, e.getResult())); } area.setText(sb.toString()); JScrollPane sp = new JScrollPane(area); JOptionPane.showMessageDialog(this, sp, "结算详情", JOptionPane.INFORMATION_MESSAGE); /* 回到结果面板 */ resultPanel.showResult(); card.show(mainPanel, "result"); }}
/* 结果面板 */
private class ResultPanel extends JPanel {
private final JTextArea area = new JTextArea(8, 30);
ResultPanel() {
setLayout(new BorderLayout());
area.setEditable(false);
area.setFont(new Font("微软雅黑", Font.PLAIN, 16));
add(new JScrollPane(area), BorderLayout.CENTER);JPanel south = new JPanel(); JButton btnAgain = new JButton("再来一套"); JButton btnWrong = new JButton("错题重练"); JButton btnMenu = new JButton("返回主菜单"); south.add(btnAgain); south.add(btnWrong); south.add(btnMenu); add(south, BorderLayout.SOUTH); btnAgain.addActionListener(e -> startNew(false)); btnWrong.addActionListener(e -> { List<Exercise> wrong = collectWrong(); if (wrong.isEmpty()) { JOptionPane.showMessageDialog(this, "暂无错题!"); return; } startNew(true); }); btnMenu.addActionListener(e -> card.show(mainPanel, "menu")); } void showResult() { int total = curExercises.size(); double rate = total == 0 ? 0 : 100.0 * curCorrect / total; StringBuilder sb = new StringBuilder(); sb.append("本次答题结束!\n"); sb.append(String.format("正确:%d / %d ,正确率:%.1f%%\n", curCorrect, total, rate)); if (curTimeout) sb.append("(已超时,未答完部分视为错题)\n"); area.setText(sb.toString()); /* 记录历史 */ history.add(new Round(curCorrect, total, curTimeout, curWrongIdx, SAVE_DIR.resolve(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss")) + ".txt"))); }}
/* 工具方法 */
private void startNew(boolean onlyWrong) {
Listlist = onlyWrong ? collectWrong() : new Generator().generate(QUESTION_CNT);
examPanel.startExam(list);
}private List
collectWrong() {
Listres = new ArrayList<>();
for (Round r : history) {
if (r.wrongFile == null) continue;
try {
Listall = ExerciseSet.importFromFile(r.wrongFile);
for (int i : r.wrongIdx) res.add(all.get(i));
} catch (IOException e) {
e.printStackTrace();
}
}
return res;
}/* ========================= 实体 / 生成器 / 文件工具 ========================= */
public static class Exercise {
private final int a, b, result;
private final char op;
private final String text;
Exercise(int a, int b, char op, int result) {
this.a = a; this.b = b; this.op = op; this.result = result;
this.text = a + "" + op + "" + b;
}
String getText() { return text; }
int getResult() { return result; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Exercise)) return false;
Exercise e = (Exercise) o;
return a == e.a && b == e.b && op == e.op;
}
@Override
public int hashCode() { return Objects.hash(a, b, op); }
}public static class Generator {
private final Sethistory = new HashSet<>();
private static final int MIN = 1, MAX = 100;
Listgenerate(int count) {
Listlist = new ArrayList<>(count);
while (list.size() < count) {
Exercise e = nextRandom();
if (history.add(e)) list.add(e);
}
return list;
}
private Exercise nextRandom() {
Random r = new Random();
while (true) {
int a = r.nextInt(MAX) + MIN;
int b = r.nextInt(MAX) + MIN;
char op = "+-/".charAt(r.nextInt(4));
switch (op) {
case '+': return new Exercise(a, b, op, a + b);
case '-': if (a < b) continue; return new Exercise(a, b, op, a - b);
case '': int m = a * b; if (m >= 1000) continue; return new Exercise(a, b, op, m);
case '/': if (b == 0 || a % b != 0) continue; return new Exercise(a, b, op, a / b);
}
}
}
}public static class ExerciseSet {
private final Listexercises;
private final String fileName;
ExerciseSet(Listexercises) {
this.exercises = exercises;
this.fileName = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss")) + ".txt";
}
String getFileName() { return fileName; }
void exportToFile(Path dir) throws IOException {
if (!Files.exists(dir)) Files.createDirectories(dir);
Path file = dir.resolve(fileName);
try (BufferedWriter w = Files.newBufferedWriter(file)) {
for (int i = 0; i < exercises.size(); i += 4) {
String line = exercises.subList(i, Math.min(i + 4, exercises.size()))
.stream().map(Exercise::getText)
.collect(java.util.stream.Collectors.joining("\t"));
w.write(line);
w.newLine();
}
}
}
static ListimportFromFile(Path file) throws IOException {
Listlist = new ArrayList<>();
Listlines = Files.readAllLines(file);
for (String line : lines) {
String[] arr = line.split("\s+");
for (String s : arr) list.add(parseExercise(s));
}
return list;
}
private static Exercise parseExercise(String s) {
char op = 0;
for (char c : s.toCharArray()) if ("+-/".indexOf(c) >= 0) { op = c; break; }
String[] sp = s.split("\" + op);
int a = Integer.parseInt(sp[0]);
int b = Integer.parseInt(sp[1]);
int r = 0;
switch (op) {
case '+': r = a + b; break;
case '-': r = a - b; break;
case '': r = a * b; break;
case '/': r = a / b; break;
}
return new Exercise(a, b, op, r);
}
}/* 成绩记录 */
public static class Round {
final int correct, total;
final boolean timeout;
final ListwrongIdx;
final Path wrongFile;Round(int correct, int total, boolean timeout, List<Integer> wrongIdx, Path wrongFile) { this.correct = correct; this.total = total; this.timeout = timeout; this.wrongIdx = wrongIdx; this.wrongFile = wrongFile; }}
}

浙公网安备 33010602011771号