课后作业

屏幕截图 2025-10-08 171632
image

image
Foo obj1 = new Foo(); // 这里调用了无参构造方法
必须传入一个 int 类型的参数来创建 Foo 对象

总结出“静态初始化块的执行顺序”。
在 Java 中,静态初始化块(static { ... })的执行顺序遵循以下核心规则:
静态初始化块执行顺序总结:

  1. 类加载时执行,且只执行一次
    当类被首次主动使用时(如:创建对象、访问静态成员、反射等),JVM 会加载该类。
    静态初始化块在类加载阶段执行,只执行一次。
  2. 父类优先于子类
    如果存在继承关系,父类的静态初始化块先于子类的静态初始化块执行。
  3. 同类中按代码顺序执行
    同一个类中,如果有多个静态初始化块,按它们在代码中出现的顺序依次执行。

image
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 List curExercises;
    private int curCorrect;
    private boolean curTimeout;
    private List curWrongIdx = new ArrayList<>();
    private final List history = 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 List answerFields = 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) {
    List list = onlyWrong ? collectWrong() : new Generator().generate(QUESTION_CNT);
    examPanel.startExam(list);
    }

    private List collectWrong() {
    List res = new ArrayList<>();
    for (Round r : history) {
    if (r.wrongFile == null) continue;
    try {
    List all = 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 Set history = new HashSet<>();
    private static final int MIN = 1, MAX = 100;
    List generate(int count) {
    List list = 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 List exercises;
    private final String fileName;
    ExerciseSet(List exercises) {
    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 List importFromFile(Path file) throws IOException {
    List list = new ArrayList<>();
    List lines = 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 List wrongIdx;
    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;
     }
    

    }
    }

posted @ 2025-10-17 17:41  克感  阅读(8)  评论(0)    收藏  举报