7-3 NCHUD-数字电路模拟程序

第一次作业

1.题目

数字电路是一种处理离散信号的电子电路。与处理连续变化信号(如声音、温度)的模拟电路不同,数字电路只识别和运算两种基本状态:高电平(通常表示为“1”)低电平(通常表示为“0”)。这正好与二进制数制系统相对应,使得数字电路成为所有计算机和数字系统的物理实现基础。

请编程实现数字电路模拟程序,

1、电路元件

电路中包含与门、或门、非门、异或门、同或门五种元件。元件特征如下:

与门:

包含两个或多个输入引脚和一个输出引脚。所有输入引脚必须都是高电平,输出引脚才是高电平,只要有一个输入引脚为低电平,输出引脚输出低电平。

或门:

包含两个或多个输入引脚和一个输出引脚。所有输入引脚必须都是低电平,输出引脚才是低电平,只要有一个输入引脚为高电平,输出引脚输出高电平。

非门:

包含一个输入引脚和一个输出引脚。输出引脚的电平与输入引脚的电平相反,如输入为低电平,输出则为高电平。

异或门:

包含两个输入引脚和一个输出引脚。当两个输入引脚电平不一致时输出引脚输出高电平,否则输出低电平。

同或门:

包含两个输入引脚和一个输出引脚。当两个输入引脚电平一致时输出引脚输出高电平,否则输出低电平。

2、程序输入

1)元件信息:

用A、O、N、X、Y 分别用作与门、或门、非门、异或门、同或门五种元件的元件标识符。

电路中的每个与门、或门用“标识符(输入引脚数)+编号”作为其元件名。

例如:A(8)1表示一个8输入引脚的与门,O(4)2代表一个4输入引脚的或门。

电路中的每个非门、异或门、同或门用“标识符+编号”作为其元件名。

例如:X8表示一个异或门,Y4代表一个同或门,N1代表一个非门。

约束条件:

不同元件的编号可以相同,如X4、Y4。

同一电路中同种元件的编号不可重复,可以不连续

2)引脚信息:

引脚信息由“元件名-引脚号”构成,。

例如:A(8)1-2代表与门A(8)1的2号引脚。

3)电路的输入信息:

电路的输入格式:

INPUT:英文空格+输入1+”-”+输入信号1+英文空格+输入2+....+输入n+”-”+输入信号n

例如:

“INPUT: A-0 B-1 C-0”代表整个电路包括3个输入:A、B、C 分别输入0,1,0信号。

4)连接信息

引脚的连接信息格式:

[+输出引脚+英文空格+输入引脚1+。。。。+英文空格+输入引脚+]

例如:

[A A(8)1-1 A(8)1-3 X5-2]

代表信号从引脚A发送给与门A(8)1的1、3两个引脚,以及异或门X5的2号引脚。

[Y8-0 N1-1 O(4)2-3 Y2-1]

代表信号从引脚Y8-0发送给非门N1的1号引脚、或门O(4)2的3号引脚、同或门Y2的1号引脚。

约束条件:

一个输出引脚可以连接多个输入引脚,即将输出引脚的信号传给每一个输入引脚。但一个输入引脚不能连接多个输出引脚。

输出引脚不能短接在一起。

5)输入结束信息

所有输入以end为结束标志,end之后出现的内容忽略不计

3、程序输出

按照与门、或门、非门、异或门、同或门的顺序依次输出所有元件的输出引脚电平。同类元件按编号从小到大的顺序排序。

如果某个元件的引脚没有接有效输入,元件输出无法计算,程序输出结果忽略该元件

4、测试输入默认满足以下条件:

1)每个元件的输入引脚连续编号。假设元件有n个输入引脚,则其编号取值范围为[1,n],且引脚号不重复。

2)本题涉及的五种元件都只有一个输出引脚,输出引脚号默认为0。

2.题目分析

题目还是比较容易理解的,就是要用代码来模拟数字电路里面的基本元件,通过连接这些元件输出每个元件输出引脚的电平。所以代码的难点就在与以下三点。

  1. 元件的解析与生成:解析输入,判断要生成什么元件。

  2. 元件的连接:实现引脚的相互连接。

  3. 信息的传播:在创建元件时是一个个创建的,引脚的电平可能会因为后面创建的元件而发生改变,所以要设置传播算法,得到稳定的电平后再输出,确保每个元件都正常工作。

3.类图

4.代码实现

(1)元件的解析与生成

流程

发现引脚字符串 → 提取元件名 → 检查是否逻辑门 → 解析元件名 → 创建门对象 → 存储到元件表
↓ ↓ ↓ ↓ ↓ ↓
"A(2)1-1" → "A(2)1" → 是逻辑门 → 解析参数 → 创建AndGate → gates["A(2)1"]

首先将输入一行行的读取,判断是INPUT还是连接语句

其次是创建PIn对象并提取元件名

再通过正则判断是否为合规的元件

然后调用parseGate() 方法来进行元件的生成

 private void parseGate(String gateName) {
        if (gates.containsKey(gateName)) return;

        Matcher matcher = GATE_PATTERN.matcher(gateName);
        if (matcher.find()) {
            String type = matcher.group(1);
            String numInputsStr = matcher.group(2);
            String id = matcher.group(3);

            LogicGate gate = null;
            switch (type) {
                case "A":
                    int andInputs = numInputsStr != null ? Integer.parseInt(numInputsStr) : 2;
                    gate = new AndGate(gateName, andInputs);
                    break;
                case "O":
                    int orInputs = numInputsStr != null ? Integer.parseInt(numInputsStr) : 2;
                    gate = new OrGate(gateName, orInputs);
                    break;
                case "N":
                    gate = new NotGate(gateName);
                    break;
                case "X":
                    gate = new XorGate(gateName);
                    break;
                case "Y":
                    gate = new XnorGate(gateName);
                    break;
            }

            if (gate != null) {
                gates.put(gateName, gate);
            }
        }
    }

(2)元件的连接

通过Map的映射来解决连接的问题2.1

第一层映射:引脚到引脚的连接关系

Map<Pin, List<Pin>> connections;

这个Map的作用:记录信号从哪里来,到哪里去

// 输入连接:[A-0 B-1 C-2 D-3]
connections = {
    Pin("A-0"): [Pin("B-1"), Pin("C-2"), Pin("D-3")],
    Pin("B-0"): [Pin("E-1")],
    Pin("C-0"): [Pin("F-1"), Pin("G-2)]
}

数据解读:

  • Pin("A-0"):信号源是A元件的输出引脚0
  • [Pin("B-1"), Pin("C-2"), Pin("D-3")]:信号发送到三个地方:
    1. B元件的输入引脚1
    2. C元件的输入引脚2
    3. D元件的输入引脚3

第二层映射:元件名到元件对象的映射

Map<String, LogicGate> gates;

这个Map的作用:记录每个元件是什么,怎么用

映射关系示例:

gates = {
    "B": AndGate对象,
    "C": OrGate对象, 
    "D": NotGate对象,
    "E": XorGate对象,
    "F": XnorGate对象,
    "G": AndGate对象
}

当处理连接行 [A-0 B-1 C-2] 时:

// 1. 创建输出引脚作为键
Pin outputPin = new Pin("A-0");  // key = Pin("A-0")

// 2. 创建输入引脚列表作为值
List<Pin> inputPins = new ArrayList<>();
inputPins.add(new Pin("B-1"));   // 添加到列表
inputPins.add(new Pin("C-2"));

// 3. 更新connections Map

(3)信号的传播

本质是基于Map的广播,有三个Map

gates Map:元件注册表

inputValues Map:输入值表

connections Map:连接表

首先把这两个输入值保存到inputValues这个Map中,相当于记录"电源A开,电源B关"

紧接着,程序立即尝试传播这些初始信号为每个输入创建一个Pin对象,比如Pin("A")会自动变成Pin("A-0")(默认输出引脚0)调用propagateSignal方法,尝试把信号传播出去
然后当某个逻辑门所有输入都到齐并且计算出输出后,这个门就变成了一个新的信号源,开始向下游传播自己的输出信号。

最后,电路中可能有多个门,它们的输入输出可能相互依赖。simulate()方法中的循环就是为了处理这种复杂的依赖关系。

  private void simulate() {
        // 重置所有门
        for (LogicGate gate : gates.values()) {
            gate.reset();
        }

        // 设置输入信号
        for (Map.Entry<String, Boolean> entry : inputValues.entrySet()) {
            Pin inputPin = new Pin(entry.getKey());
            propagateSignal(inputPin, entry.getValue());
        }

        // 多次传播直到稳定
        boolean changed;
        int iterations = 0;
        do {
            changed = false;
            iterations++;

            for (LogicGate gate : gates.values()) {
                if (gate.hasAllInputs() && gate.getOutput() == null) {
                    if (gate.calculateOutput()) {
                        changed = true;
                        Pin outputPin = new Pin(gate.getName() + "-0");
                        propagateSignal(outputPin, gate.getOutput());
                    }
                }
            }
        } while (changed && iterations < 100);
    }

5.代码效率分析

Metrics Details For File 'Main.java'
--------------------------------------------------------------------------------------------

Parameter				Value
=========				=====
Project Directory			D:\IDEACODE\dianziyuanjian1\dian1\src\fsefe\
Project Name				
Checkpoint Name				Baseline
File Name				Main.java
Lines					377
Statements				242
Percent Branch Statements		23.6
Method Call Statements			96
Percent Lines with Comments		4.0
Classes and Interfaces			8
Methods per Class			4.13
Average Statements per Method		5.61
Line Number of Most Complex Method	158
Name of Most Complex Method		Main.parseGate()
Maximum Complexity			12
Line Number of Deepest Block		170
Maximum Block Depth			5
Average Block Depth			2.02
Average Complexity			2.31

--------------------------------------------------------------------------------------------
Most Complex Methods in 9 Class(es):	Complexity, Statements, Max Depth, Calls

AndGate.AndGate()			1, 1, 2, 1
AndGate.calculateOutput()		3, 7, 3, 2
getSortedOutput().outputGates.sort(()	2, 8, 3, 6
LogicGate.getName()			1, 1, 2, 0
LogicGate.getOutput()			1, 1, 2, 0
LogicGate.getType()			1, 1, 2, 0
LogicGate.hasAllInputs()		3, 4, 4, 1
LogicGate.LogicGate()			1, 5, 2, 0
LogicGate.reset()			1, 2, 2, 1
LogicGate.setInput()			1, 1, 2, 1
Main.Main()				1, 3, 2, 0
Main.parseGate()			12, 28, 5, 9
Main.processConnection()		5, 10, 4, 7
Main.processInput()			4, 6, 5, 4
NotGate.calculateOutput()		2, 4, 2, 1
NotGate.NotGate()			1, 1, 2, 1
OrGate.calculateOutput()		3, 7, 3, 2
OrGate.OrGate()				1, 1, 2, 1
Pin.equals()				5, 6, 2, 3
Pin.hashCode()				1, 1, 2, 1
Pin.Pin()				3, 7, 3, 3
Pin.toString()				1, 1, 2, 0
XnorGate.calculateOutput()		2, 4, 2, 3
XnorGate.XnorGate()			1, 1, 2, 1
XorGate.calculateOutput()		2, 4, 2, 3
XorGate.XorGate()			1, 1, 2, 1

--------------------------------------------------------------------------------------------
Block Depth				Statements

0					18
1					72
2					88
3					32
4					16
5					16
6					0
7					0
8					0
9+					0
--------------------------------------------------------------------------------------------

第二次作业

1.题目(我只贴了新加的)

#三态门:

三态门的作用类似于电路中的开关。包含一个输入引脚、一个输入控制引脚、一个输出引脚。当控制引脚为高电平时,三态门输入输出之间导通,输出电平等于输入电平;当控制引脚为低电平时,三态门输入输出之间呈现高阻态(类似开关断开),输出为无效状态。

#译码器:

译码器的作用是讲输入的编码转换为一路有效信号。一个译码器包含两个或多个输入引脚(如图中的A2\A1\A0)、三个控制引脚(如图中的S3\S2\S1)、4个或多个输出引脚(如图中的Y7~Y0)。根据输入输出的数量有2-4线译码器、3-8线译码器等。

当控制引脚当S1 =1,S2 +S3 =0时,译码器正常工作,输出引脚只有一个输出信号0,其余输出为1;哪个引脚输出0由输入引脚的编码决定,例如:图中的3-8线译码器三个输入引脚信号的编码与输出引脚的编码对应,A2\A1\A0输入000时,Y0输出0,其余输出1;A2\A1\A0输入001时,Y1输出0,其余输出1;依次类推。

控制引脚不满足S1 =1,S2 +S3 =0时,译码器处于无效状态,所有输出为无效值。

#数据选择器:

数据选择器的作用是从多路输入信号中选择一个,并将其信号直接送往唯一的输出端,选择哪一路输入信号由控制端决定。如图所示控制端有两个则输入端有4个,S1\S0是两个控制端,D3D0是输入端,S1\S0的4种信号组合00、01、10、11分别选择D3D0其中一路输入。如S1S0=00,则Y=D0;S1S0=01,则Y=D1;S1S0=10,则Y=D2;S1S0=11,则Y=D3

根据输入引脚数量的不同有二选一数据选择器(1个控制端)、四选一数据选择器(2个控制端)、八选一数据选择器(3个控制端)等

#数据分配器:

数据分配器的作用与数据选择器正好相反,是将唯一的一路输入信号输出到多路输出引脚的其中之一,选择哪一路输出引脚输出由控制端决定。如图所示控制端有两个AB,输出端有4个W0\W1\W2\W3,D是输入端,AB的4种信号组合00、01、10、11分别选择W3~W0其中一路输出,其他三路输出为无效状态。如AB=00,则W0=D;AB=01,则W1=D;AB=10,则W2=D;AB=11,则W3=D。

根据输出引脚数量的不同有二路数据分配器(1个控制端)、四路数据分配器(2个控制端)、八路数据分配器(3个控制端)等

2)#引脚信息:

引脚信息由“元件名-引脚号”构成。

例如:A(8)1-2代表与门A(8)1的2号引脚。

#含控制引脚的元件如本次添加的所有元件,按控制-输入-输出的顺序排序,
每种类型的引脚按编号从小到大的顺序排序,
例如3-8线译码器M(3)1包含3个输入引脚、3个控制引脚、8个输出引脚,
    M(3)1-0/1/2对应控制引脚S1/S2/S3,
    M(3)1-3/4/5对应输入引脚A0/A1/A2,
    M(3)1-6/7/8/9/10/11/12/13对应输出引脚Y0\~Y7。
又如三态门的三个引脚,0号引脚为控制端、1号引脚为输入端、2号引脚为输出端

2.题目分析

在第一次的基础逻辑上新增4种元件,入手还是从那三个方面入手。

3.类图

4.代码实现

(1)元件的解析与生成

主要就是改了一下判断元件是否合法的正则表达式

Pattern.compile("([AONXYSMZF])(?:\\((\\d+)\\))?(\\d+)")

还有修改了工厂的方法

switch (type) {
    // 保留基础门逻辑...
    case "S": // 三态门,固定2个输入引脚
        gate = new TriStateGate(gateName);
        break;
    case "M": // 译码器,参数为输入引脚数(默认3)
        int decoderInputs = numStr != null ? Integer.parseInt(numStr) : 3;
        gate = new Decoder(gateName, decoderInputs);
        break;
    case "Z": // 多路选择器,参数为控制引脚数(默认2)
        int muxControlPins = numStr != null ? Integer.parseInt(numStr) : 2;
        gate = new Multiplexer(gateName, muxControlPins);
        break;
    case "F": // 多路分配器,参数为控制引脚数(默认2)
        int demuxControlPins = numStr != null ? Integer.parseInt(numStr) : 2;
        gate = new Demultiplexer(gateName, demuxControlPins);
        break;
}

第一次输出只有0与1,新加了一个是否有效的标识

protected boolean hasValidOutput;
public void reset() { 
    inputs.clear(); output = null; hasValidOutput = false; 
}

(2)元件的连接

第一次代码中,基础门的引脚规则很简单:
输入引脚:从 1 开始编号
输出引脚:固定为 0
第二次代码为新增元件定义了非标准引脚编号规则,连接逻辑需要适配这些规则:
三态门:输入引脚为 0(控制)、1(数据),输出引脚为 2。
译码器:控制引脚 0-2、输入引脚 3-N、输出引脚 N+1-...。
多路选择器 / 分配器:控制引脚、数据引脚、输入引脚分段编号。
这些特殊引脚编号会被 Pin 类正常解析,进而存入 connections 参与连接。

class Pin {
    String component;
    int pinNumber;

    public Pin(String pinStr) {
        if (pinStr.contains("-")) {
            String[] parts = pinStr.split("-");
            this.component = parts[0];
            try {
                this.pinNumber = Integer.parseInt(parts[1]);
            } catch (NumberFormatException e) {
                this.pinNumber = 0;
            }
        } else {
            this.component = pinStr;
            this.pinNumber = 0;
        }
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Pin pin = (Pin) obj;
        return pinNumber == pin.pinNumber && Objects.equals(component, pin.component);
    }

    @Override
    public int hashCode() {
        return Objects.hash(component, pinNumber);
    }

    @Override
    public String toString() {
        return component + "-" + pinNumber;
    }
}

(3)信号的传播

第二次新增了setGateInput方法,保证状态一致性,由于第一次的 propagateSignal方法仅做单层传播,没有处理目标门的输出变化是否会影响后续门,会导致一个测试点过不去,所以新增加了setGateInput方法,并修改 propagateSignal 调用它,实现递归传播。

 private void setGateInput(LogicGate gate, int pin, boolean value) {
        gate.setInput(pin, value);

        Pin sourcePin = new Pin(gate.getName() + "-" + pin);
        if (connections.containsKey(sourcePin)) {
            for (Pin targetPin : connections.get(sourcePin)) {
                LogicGate targetGate = gates.get(targetPin.component);
                if (targetGate != null) {
                    setGateInput(targetGate, targetPin.pinNumber, value);
                }
            }
        }
    }

    private void propagateSignal(Pin sourcePin, boolean value) {
        if (connections.containsKey(sourcePin)) {
            for (Pin targetPin : connections.get(sourcePin)) {
                LogicGate targetGate = gates.get(targetPin.component);
                if (targetGate != null) {
                    setGateInput(targetGate, targetPin.pinNumber, value);
                }
            }
        }
    }

5.代码效率分析

Metrics Details For File 'Main.java'
--------------------------------------------------------------------------------------------

Parameter				Value
=========				=====
Project Directory			D:\IDEACODE\dianziyuanjian1\dian2\src\dww\
Project Name				
Checkpoint Name				Baseline
File Name				Main.java
Lines					712
Statements				481
Percent Branch Statements		23.7
Method Call Statements			178
Percent Lines with Comments		1.4
Classes and Interfaces			12
Methods per Class			4.58
Average Statements per Method		6.18
Line Number of Most Complex Method	488
Name of Most Complex Method		Main.simulate()
Maximum Complexity			23
Line Number of Deepest Block		533
Maximum Block Depth			9+
Average Block Depth			2.57
Average Complexity			2.90

--------------------------------------------------------------------------------------------
Most Complex Methods in 12 Class(es):	Complexity, Statements, Max Depth, Calls

AndGate.AndGate()			1, 1, 2, 1
AndGate.calculateOutput()		3, 9, 3, 2
Decoder.calculateOutput()		7, 17, 4, 5
Decoder.Decoder()			1, 5, 2, 1
Decoder.getActiveOutput()		1, 1, 2, 0
Decoder.getControlPins()		1, 1, 2, 0
Decoder.getInputPins()			1, 1, 2, 0
Decoder.getOutputPins()			1, 1, 2, 0
Decoder.hasAllInputs()			3, 4, 4, 1
Demultiplexer.calculateOutput()		6, 17, 4, 6
Demultiplexer.Demultiplexer()		1, 4, 2, 2
Demultiplexer.getControlPins()		1, 1, 2, 0
Demultiplexer.getOutputPins()		1, 1, 2, 0
Demultiplexer.getOutputs()		1, 1, 2, 0
Demultiplexer.hasAllInputs()		3, 4, 4, 1
LogicGate.getName()			1, 1, 2, 0
LogicGate.getOutput()			1, 1, 2, 0
LogicGate.getType()			1, 1, 2, 0
LogicGate.hasAllInputs()		3, 4, 4, 1
LogicGate.hasValidOutput()		1, 1, 2, 0
LogicGate.LogicGate()			1, 6, 2, 0
LogicGate.reset()			1, 3, 2, 1
LogicGate.setInput()			1, 1, 2, 1
Main.getSortedOutput()			1, 4, 2, 4
Main.isLogicGate()			1, 1, 2, 1
Main.Main()				1, 3, 2, 0
Main.parseGate()			19, 43, 5, 12
Main.processConnection()		7, 12, 6, 9
Main.processInput()			4, 6, 5, 4
Main.propagateSignal()			4, 5, 5, 4
Main.setGateInput()			4, 7, 5, 6
Main.simulate()				23, 47, 10, 32
Multiplexer.calculateOutput()		5, 14, 4, 4
Multiplexer.getControlPins()		1, 1, 2, 0
Multiplexer.getDataPins()		1, 1, 2, 0
Multiplexer.hasAllInputs()		5, 9, 4, 3
Multiplexer.Multiplexer()		1, 3, 2, 1
NotGate.calculateOutput()		2, 6, 3, 1
NotGate.NotGate()			1, 1, 2, 1
OrGate.calculateOutput()		3, 9, 3, 2
OrGate.OrGate()				1, 1, 2, 1
Pin.equals()				5, 6, 2, 3
Pin.hashCode()				1, 1, 2, 1
Pin.Pin()				4, 10, 4, 3
Pin.toString()				1, 1, 2, 0
TriStateGate.calculateOutput()		5, 12, 3, 4
TriStateGate.hasAllInputs()		2, 1, 2, 2
TriStateGate.TriStateGate()		1, 1, 2, 1
XnorGate.calculateOutput()		2, 6, 3, 3
XnorGate.XnorGate()			1, 1, 2, 1
XorGate.calculateOutput()		2, 6, 3, 3
XorGate.XorGate()			1, 1, 2, 1

--------------------------------------------------------------------------------------------
Block Depth				Statements

0					21
1					118
2					167
3					71
4					39
5					31
6					5
7					9
8					15
9+					5
--------------------------------------------------------------------------------------------

实验心得

在完成逻辑门电路仿真实验的过程中,我不仅亲手搭建了从基础门电路到复杂组合逻辑电路的仿真模型,更对面向对象编程思想与数字电路原理的结合有了深刻的理解。

实验初期,通过定义LogicGate抽象类,再派生出不同功能的门电路子类,我体会到了面向对象编程中抽象与封装的魅力。每个门电路都封装了自身的计算逻辑,calculateOutput方法的抽象设计,让不同门电路的输出计算既统一又独立。而输入引脚的状态管理、输出有效性的判断,也让我意识到,编程实现硬件逻辑时,必须精准对应物理元件的特性,比如 “只有输入全部就绪,才能计算输出” 这一细节,正是硬件电路工作的基本逻辑。

随着实验深入,新增三态门、译码器、多路选择器等复杂元件时,挑战也随之而来。这些元件不再是简单的输入输出映射,而是带有控制逻辑和多输出特性。比如三态门的 “高阻态” 设计,需要引入hasValidOutput属性来标识输出是否有效;译码器的 “一激活多禁用” 逻辑,要求我们对输出引脚进行精细化的信号传播。这让我明白,复杂系统的构建需要分层设计:先定义好基础元件的接口标准,再通过扩展属性和方法适配特殊元件,同时要保证信号传播的一致性。这次实验中,递归式的setGateInput方法设计,就很好地解决了多级电路连接时的状态同步问题。

此外,实验中的调试过程也让我收获颇丰。从最初的引脚编号混乱导致信号传播错误,到后来的输出格式不统一问题,每一次调试都是对逻辑严谨性的考验。尤其是在处理译码器和多路分配器的差异化输出时,我学会了根据元件功能设计专属的输出生成规则,让仿真结果更贴合实际硬件的表现。

这次实验不仅巩固了我对数字电路原理的认识,更提升了我运用面向对象思想解决实际问题的能力。它让我深刻体会到,编程不只是代码的堆砌,更是对现实逻辑的精准建模。未来在面对更复杂的系统开发时,我会更加注重底层逻辑的梳理和模块化设计,让代码既高效又具备良好的扩展性。

课堂测验

题目 2:子类重写父类方法时,哪些规则是正确的?

A. 方法名相同

B. 参数相同

C. 返回类型与父类定义相同或是父类返回类型的子类

D. 访问权限 >= 父类被重写的方法定义的访问权限

正确答案:ABCD
解析(重写的 “两同两小一大” 规则)
两同:方法名相同(A)、参数列表完全相同(B)(参数类型 / 个数 / 顺序一致);
返回值协变:返回类型可以是父类返回类型的子类(C),例如父类返回Object,子类可返回String;
一大:子类方法访问权限 ≥ 父类(D)(父类protected,子类可protected/public;父类public,子类只能public);

题目 3:关于 super 关键字,以下说法哪些是正确的?(周雪芹 答错)
选项
A. super 关键字可以调用父类的构造方法B. super 关键字可以调用父类的普通方法C. super 关键字与 this 不能同时存在于同一个构造方法中D. super 关键字与 this 可以同时存在于同一个构造方法中
正确答案:ABD
解析
A 正确:super(参数)可调用父类构造方法,且必须放在子类构造方法第一行;
B 正确:super.方法名(参数)可调用父类的普通方法(解决子类重写后想调用父类原方法的场景);
C 错误,D 正确:super和this可以共存于同一构造方法(只要super/this都在第一行,且不同时出现)。
题目 4:对 String 类型的字符串 String str="123";,调用 str 对象的 () 方法,得到 int 类型的十进制整型数值 123?(周雪芹 答错)
选项
A. int i1=Integer.parseInt(str);B. int i2=new Integer(str);C. int i3=Integer.parseInt(str, 10);D. int i4=str.toInteger();
正确答案:ABC
解析
A 正确:Integer.parseInt(String s) 默认按十进制解析字符串为 int;
B 正确:new Integer(str) 创建 Integer 对象,自动拆箱为 int(Java 5 + 支持自动拆箱);
C 正确:Integer.parseInt(String s, int radix) 中radix=10显式指定十进制,效果同 A;
D 错误:String 类无toInteger()方法。

题目 5:在 java 中,已定义了两个接口 B 和 C,下面继承语句正确的是(刘生智 答错)
选项
A. interface A extends B,CB. interface A implements B,CC. class A implements B,CD. class A implements B,implements C
正确答案:AC
解析
A 正确:接口之间用extends实现多继承(Java 唯一支持多继承的场景);
B 错误:接口不能用implements继承其他接口,只能用extends;
C 正确:类实现多个接口时,用implements+ 多个接口名(逗号分隔);
D 错误:implements关键字只需写一次,多个接口用逗号分隔即可。

题目 10:在 Java 的类继承层次中,以下哪些修饰符不能用于顶层类 ?(马俊 答错)
选项
A. publicB. privateC. abstractD. final
正确答案:B
解析
顶层类:指不嵌套在其他类中的独立类(区别于内部类);
A 可以:public是顶层类的常见修饰符(可跨包访问);
B 不可以:private修饰的类只能在当前类内部访问,顶层类无 “外部类”,因此private修饰顶层类编译报错;
C 可以:abstract修饰顶层抽象类(不能实例化,仅用于被继承);
D 可以:final修饰顶层类(不能被继承)。

测试薄弱点分析

一、面向对象核心特性理解不透彻
这是本次测试失分最多的模块,尤其体现在接口与抽象类的区别、方法重写规则、super关键字用法三个题型上。在接口与抽象类的题目中,我错误地认为“抽象类没有构造函数”,忽略了抽象类本质仍是类,其构造函数用于子类初始化父类属性的核心作用。在方法重写规则的题目中,我未能准确把握“返回值协变”和“访问权限≥父类”的细节要求,误以为返回值必须与父类完全一致,从而错失正确选项。而对于super关键字,我错误地认为它与this不能共存于同一构造方法中,忽略了两者只要不同时位于第一行即可共存的规则,反映出对构造方法初始化流程的理解不清晰。

二、数组与字符串操作规则掌握不牢固

在二维数组初始化和字符串操作的题目中,我的错误暴露了对相关规则的记忆混淆。二维数组初始化时,我不清楚“必须指定行维度,列维度可省略”的规则,误选了“int a[][]=new int[][3]”这种非法写法;同时对不规则二维数组的合法性认知不足,未能准确判断正确选项。在字符串操作中,我混淆了字符串与数组的访问方式,误以为可以用“s[3]”访问字符串中的字符,忽略了String类需通过charAt()方法访问指定位置字符的规则;此外,还错误地认为字符串支持“-”运算符,违背了字符串仅支持“+”拼接的基本常识,这些错误都反映出对数组和字符串的核心操作规则掌握不扎实。

posted @ 2025-12-14 19:57  iW_Wi  阅读(3)  评论(0)    收藏  举报