Skip to content

《面向对象程序设计(Java)》期末试卷A (精选01)

一、选择题(共 20 题,每题 1.5 分,共 30 分)

1.运行名为 Test.class 的 Java 字节码文件,所用的 Java 命令是( )

  • A. javac Test.java
  • B. javac Test.class
  • C. java Test
  • D. java Test.class
查看答案与解析

答案:C

解析:

  • javac 是 Java 编译器,用于将 .java 源文件编译为 .class 字节码文件,A、B 错误。
  • java 是 Java 虚拟机启动命令,运行字节码文件时不需要加 .class 后缀,只需写类名。
  • 正确命令:java Test,C 正确,D 错误。

难度: ⭐ 考点: #Java命令 #javac #java

💡 学习锦囊

📖 相关公式与知识点:

  • javac:编译器,将 .java 源文件编译为 .class 字节码文件
  • java:虚拟机启动命令,运行字节码文件(不加 .class 后缀)

易错点

  • java Test 运行时不加 .class 后缀
  • javac 后面跟源文件名(带 .java),java 后面跟类名(不带后缀)
🔄 举一反三
  1. 如果源文件名为 HelloWorld.java,编译和运行的命令分别是什么?
    查看练习答案与解析

    答案:编译 javac HelloWorld.java,运行 java HelloWorld解析:javac 编译源文件需要带 .java 后缀,java 运行类不需要后缀。

2.下列不可作为 Java 语言标识符的是( )

  • A. a2
  • B. $2
  • C. _2
  • D. 22
查看答案与解析

答案:D

解析: Java 标识符命名规则:

  • 可以由字母、数字、下划线 _、美元符号 $ 组成

  • 不能以数字开头

  • 不能使用 Java 关键字

  • A:a2 以字母开头,合法 ✓

  • B:$2 以 $ 开头,合法 ✓

  • C:_2 以下划线开头,合法 ✓

  • D:22 以数字开头,非法


难度: ⭐ 考点: #标识符 #命名规则

💡 学习锦囊

📖 相关公式与知识点:

  • 标识符规则:字母/_/$ 开头,不含关键字,区分大小写
  • 不能以数字开头

易错点

  • $_ 可以作为标识符开头
  • 数字不能作为标识符开头,但可以出现在中间
🔄 举一反三
  1. 下列哪个是合法的 Java 标识符?
    • A. class
    • B. _name
    • C. 3abc
    • D. my-name
    查看练习答案与解析

    答案:B 解析:A 是 Java 关键字;B 以下划线开头,合法;C 以数字开头,非法;D 含连字符,非法。

3.以下关于运算符优先级顺序的描述中正确的是( )

  • A. 关系运算符 < 算术运算符 < 赋值运算符
  • B. 赋值运算符 < 关系运算符 < 算术运算符
  • C. 算术运算符 < 关系运算符 < 赋值运算符
  • D. 赋值运算符 < 算术运算符 < 关系运算符
查看答案与解析

答案:B

解析: Java 运算符优先级(从高到低):算术运算符 > 关系运算符 > 赋值运算符

用"<"表示"优先级低于":赋值运算符 < 关系运算符 < 算术运算符


难度: ⭐⭐ 考点: #运算符优先级

💡 学习锦囊

📖 相关公式与知识点:

  • 运算符优先级:算术 > 关系 > 逻辑 > 赋值
  • 赋值运算符优先级最低

易错点

  • 赋值运算符优先级最低
  • 逻辑运算符介于关系运算符和赋值运算符之间
🔄 举一反三
  1. 表达式 a + b > c && d == e 中,运算符的执行顺序是?
    查看练习答案与解析

    答案:先 a+b,再 >c==e,最后 &&解析:算术(+) → 关系(>, ==) → 逻辑(&&),按优先级从高到低执行。

4.getCustomerInfo() 方法如下,try 中可以捕获三种类型的异常,如果在该方法中产生了一个 IOException,将会输出什么结果( )

java
public void getCustomerInfo() {
    try {
        // do something that may cause an Exception
    } catch (java.io.FileNotFoundException ex) {
        System.out.print("FileNotFoundException!");
    } catch (java.io.IOException ex) {
        System.out.print("IOException!");
    } catch (java.lang.Exception ex) {
        System.out.print("Exception!");
    }
}
  • A. IOException!
  • B. IOException!Exception!
  • C. FileNotFoundException!IOException!
  • D. FileNotFoundException!IOException!Exception!
查看答案与解析

答案:A

解析: 异常捕获的匹配规则:从上到下依次匹配,第一个匹配的 catch 块执行后,后面的 catch 块不再执行

异常类的继承关系:FileNotFoundExceptionIOExceptionException

当产生 IOException 时:

  1. FileNotFoundExceptionIOException 的子类,不匹配 → 跳过
  2. IOException 精确匹配 → 执行,输出 IOException!
  3. Exception 虽然也能匹配,但已被前面的 catch 捕获 → 不执行

难度: ⭐⭐ 考点: #异常处理 #异常捕获顺序

💡 学习锦囊

📖 相关公式与知识点:

  • 异常捕获顺序:子类异常必须在父类异常之前
  • 多 catch 块:从上到下匹配,第一个匹配的执行后不再继续

易错点

  • 多个 catch 块只执行第一个匹配的,不会全部执行
  • 子类异常必须写在父类异常之前,否则编译报错
🔄 举一反三
  1. 如果产生 FileNotFoundException,会输出什么?
    查看练习答案与解析

    答案FileNotFoundException!解析FileNotFoundException 精确匹配第一个 catch 块,执行后不再继续。

5.声明成员变量时,如果不使用任何访问控制符,则以下哪种类型的类不能对该成员进行直接访问( )

  • A. 同一类
  • B. 同一包中的子类
  • C. 同一包中的非子类
  • D. 不同包中的子类
查看答案与解析

答案:D

解析: 不使用任何访问控制符时,成员的访问权限为默认(包访问权限/default)

访问者能否访问
同一类
同一包中的子类
同一包中的非子类
不同包中的子类
不同包中的非子类

难度: ⭐ 考点: #访问修饰符 #default权限

💡 学习锦囊

📖 相关公式与知识点:

  • private:本类可访问
  • default(无修饰符):本包可访问
  • protected:本包 + 其他包的子类可访问
  • public:所有类可访问

易错点

  • default 权限不允许跨包访问,即使是子类也不行
  • protected 允许跨包的子类访问,这是与 default 的关键区别
🔄 举一反三
  1. 如果成员用 protected 修饰,不同包中的子类能否访问?
    查看练习答案与解析

    答案:能 解析:protected 允许同包的所有类和不同包的子类访问。

6.对于下列代码:

java
String str1 = "java";
String str2 = "java";
String str3 = new String("java");
StringBuffer str4 = new StringBuffer("java");

下列结论正确的是( )

  • A. str1 == str2
  • B. str1 == str4
  • C. str2 == str3
  • D. str3 == str4
查看答案与解析

答案:A

解析:== 比较的是引用(地址),equals() 比较的是内容。

  • str1 = "java"str2 = "java":字符串字面量存储在字符串常量池中,相同内容共享同一对象,所以 str1 == str2true,A 正确。
  • str3 = new String("java")new 在堆内存中创建新对象,与常量池中的对象地址不同,str2 == str3 为 false,C 错误。
  • str4 = new StringBuffer("java"):StringBuffer 是不同类型,与 String 比较 == 必然为 false,B、D 错误。

难度: ⭐⭐ 考点: #String比较 #字符串常量池 #==与equals

💡 学习锦囊

📖 相关公式与知识点:

  • String 常量池:字面量共享同一对象,new 创建新对象
  • ==:比较引用(地址)
  • equals():比较内容

易错点

  • new String("java") 创建新对象,与常量池中的 "java" 地址不同
  • == 比较地址,equals() 比较内容
🔄 举一反三
  1. 以下代码输出什么?
    java
    String s1 = "hello";
    String s2 = new String("hello");
    System.out.println(s1 == s2);
    System.out.println(s1.equals(s2));
    查看练习答案与解析

    答案false 然后 true解析s1 在常量池中,s2 在堆内存中,== 比较地址不同所以 false;equals() 比较内容相同所以 true。

7.关于接口,下面的叙述错误的是( )

  • A. 一个接口可以继承多个接口
  • B. 一个类可以实现多个接口
  • C. 抽象类在实现接口时,可以不实现该接口中声明的所有方法
  • D. 抽象类在实现接口时,必须实现该接口中声明的所有方法
查看答案与解析

答案:D

解析:

  • A 正确:接口支持多继承
  • B 正确:类可以实现多个接口
  • C 正确:抽象类实现接口时,可以只实现部分方法,未实现的方法仍为抽象方法
  • D 错误:抽象类实现接口时,不需要实现所有方法

难度: ⭐⭐ 考点: #接口 #抽象类 #多继承

💡 学习锦囊

📖 相关公式与知识点:

  • 接口多继承:接口可以继承多个接口
  • 类多实现:一个类可以实现多个接口
  • 抽象类实现接口:可以只实现部分方法

易错点

  • 抽象类实现接口时不需要实现所有方法
  • 具体类(非抽象类)实现接口时必须实现所有方法
🔄 举一反三
  1. 如果一个具体类实现了一个接口但没有实现所有方法,会怎样?
    查看练习答案与解析

    答案:编译报错 解析:具体类必须实现接口中的所有抽象方法,否则必须声明为抽象类。

8.以下程序运行的结果是( )

java
public class Test {
    public int div(int a, int b) {
        try {
            return a / b;
        } catch (Exception e) {
            System.out.println("Exception");
        } catch (NULLException e) {
            System.out.println("NullException");
        } catch (ArithmeticException e) {
            System.out.println("ArithmeticException");
        } finally {
            System.out.println("finally");
        }
        return 0;
    }
    public static void main(String[] args) {
        Test demo = new Test();
        System.out.println("商是:" + demo.div(9, 10));
    }
}
  • A. Exception finally 商是:0
  • B. ArithmeticException finally 商是:0
  • C. finally 商是:0
  • D. 编译报错
查看答案与解析

答案:D

解析: Java 异常捕获要求:子类异常必须写在父类异常之前,否则编译报错。

代码中 catch(Exception e) 写在最前面,而 ArithmeticExceptionException 的子类,后面的 catch(ArithmeticException e) 永远不可达,编译器报错。

此外,NullException 不是 Java 标准异常类(标准类为 NullPointerException),也会导致编译错误。


难度: ⭐⭐⭐ 考点: #异常处理 #catch顺序 #编译错误

💡 学习锦囊

📖 相关公式与知识点:

  • catch 顺序:子类异常必须在父类异常之前
  • 不可达代码:如果父类异常在前,子类异常的 catch 块永远不可达

易错点

  • 子类异常必须写在父类异常之前,否则编译报错
  • NullException 不是 Java 标准异常类
🔄 举一反三
  1. 将 catch 顺序调整为 ArithmeticExceptionException,调用 div(9, 0) 输出什么?
    查看练习答案与解析

    答案ArithmeticException 然后 finally 然后 商是:0解析:9/0 抛出 ArithmeticException,匹配第一个 catch 输出 "ArithmeticException",finally 始终执行,最后 return 0 输出 "商是:0"。

9.在某个类中存在一个方法:void getSort(int x),以下能作为这个方法的重载的声明的是( )

  • A. public get(float x)
  • B. int getSort(int y)
  • C. double getSort(int x, int y)
  • D. void get(int x, int y) {}
查看答案与解析

答案:C

解析: 方法重载要求:方法名相同,参数列表不同,与返回类型无关。

  • A:方法名为 get,不是重载 ✗
  • B:参数列表相同(形参名不同不算),仅返回类型不同,不是合法重载
  • C:参数个数不同,合法重载
  • D:方法名为 get,不是重载 ✗

难度: ⭐⭐ 考点: #方法重载 #参数列表

💡 学习锦囊

📖 相关公式与知识点:

  • 方法重载:同名不同参,与返回类型无关
  • 形参名不同不算重载

易错点

  • 方法重载只看参数列表,不看返回类型和形参名
  • 仅返回类型不同不是合法重载
🔄 举一反三
  1. 下列哪个是 public void show(int a) 的合法重载?
    • A. public int show(int b)
    • B. public void show(double a)
    • C. public void show()
    • D. B 和 C 都合法
    查看练习答案与解析

    答案:D 解析:A 参数相同仅返回类型不同,不合法;B 参数类型不同,合法;C 参数个数不同,合法。

10.以下哪句是错误的?( )

  • A. 编译器会搜索要 import 的类的编译结果而不是源文件
  • B. import 是要告诉编译器要 import 的包的信息
  • C. import 是要把 import 的类的源代码插入到 import 语句所在的地方
  • D. 编译器在编译的时候需要能访问得到 import 的类的编译结果文件
查看答案与解析

答案:C

解析:

  • A 正确:编译器查找的是 .class 文件
  • B 正确:import 语句告诉编译器所需类的包路径信息
  • C 错误import 不会将源代码插入到当前位置,它只是告诉编译器去哪里找类
  • D 正确:编译时需要能访问到被 import 类的 .class 文件

难度: ⭐⭐ 考点: #import #编译机制

💡 学习锦囊

📖 相关公式与知识点:

  • import 作用:告诉编译器类的包路径,不是插入源代码
  • 与 C 的 #include 区别#include 是插入源代码,import 是指明路径

易错点

  • Java 的 import 不等于 C 语言的 #include
  • import 不会将源代码插入到当前位置
🔄 举一反三
  1. import java.util.*; 的作用是什么?
    查看练习答案与解析

    答案:告诉编译器在 java.util 包中查找所需的类 解析:通配符 * 表示导入包中所有类,但不会实际加载所有类,只在需要时查找。

11.在 Java 中,关于 HashMap 类的描述,以下选项错误的是( )

  • A. HashMap 使用键/值的形式保存数据
  • B. HashMap 能够保证其中元素的顺序
  • C. HashMap 允许将 null 用作键
  • D. HashMap 允许将 null 用作值
查看答案与解析

答案:B

解析:

  • A 正确:HashMap 基于哈希表,以键值对形式存储数据
  • B 错误:HashMap 不保证元素的顺序。如需有序,应使用 LinkedHashMapTreeMap
  • C 正确:HashMap 允许一个 null 键
  • D 正确:HashMap 允许多个 null 值

难度: ⭐⭐ 考点: #HashMap #集合框架

💡 学习锦囊

📖 相关公式与知识点:

  • HashMap:基于哈希表,键值对存储,不保证顺序
  • LinkedHashMap:保持插入顺序
  • TreeMap:按键的自然顺序排序

易错点

  • HashMap 不保证元素顺序
  • 如需有序 Map,使用 LinkedHashMap 或 TreeMap
🔄 举一反三
  1. 如果需要按插入顺序遍历 Map,应该使用哪个类?
    查看练习答案与解析

    答案:LinkedHashMap 解析:LinkedHashMap 在 HashMap 基础上维护了双向链表,保持键值对的插入顺序。

12.以下说法错误的是( )

  • A. 静态方法可以直接访问本类的静态变量和静态方法
  • B. 静态方法可以直接访问本类的非静态变量和非静态方法
  • C. 非静态方法可以直接访问本类的静态变量和静态方法
  • D. 非静态方法可以直接访问本类的非静态变量和非静态方法
查看答案与解析

答案:B

解析:

  • A 正确:静态方法属于类,可以直接访问类的静态成员
  • B 错误:静态方法不能直接访问非静态成员(非静态成员属于对象实例,需要先创建对象才能访问)
  • C 正确:非静态方法中可以直接访问静态成员
  • D 正确:非静态方法中可以直接访问同类的其他非静态成员

难度: ⭐⭐ 考点: #static #静态方法

💡 学习锦囊

📖 相关公式与知识点:

  • 静态方法:属于类,可直接访问静态成员,不能直接访问非静态成员
  • 非静态方法:属于对象,可直接访问静态和非静态成员

易错点

  • 静态方法不能直接访问非静态成员,必须通过对象引用
  • 非静态方法可以访问静态成员
🔄 举一反三
  1. 在静态方法中如何访问非静态成员?
    查看练习答案与解析

    答案:创建类的对象,通过对象引用访问 解析:如 MyClass obj = new MyClass(); obj.nonStaticMethod();

13.下列哪个选项定义的抽象类是正确的?( )

  • A. public abstract final class Car { abstract void move(); }
  • B. public class abstract Car { abstract void move(); }
  • C. public abstract class Car { abstract void drive(); }
  • D. public abstract class Car { abstract void drive() { } }
查看答案与解析

答案:C

解析:

  • A:abstractfinal 不能同时修饰类 ✗
  • B:关键字顺序错误,abstract 应在 class 之前 ✗
  • C:语法正确 ✓
  • D:抽象方法不能有方法体 { }

难度: ⭐⭐ 考点: #抽象类 #抽象方法 #final

💡 学习锦囊

📖 相关公式与知识点:

  • 抽象类:用 abstract 修饰
  • 抽象方法:只有声明,没有方法体
  • abstract 与 final:不能同时修饰类

易错点

  • 抽象方法不能有方法体 { }
  • abstractfinal 不能同时修饰类
🔄 举一反三
  1. 下列哪个抽象方法定义是正确的?
    • A. abstract void show() { }
    • B. abstract void show();
    • C. void abstract show();
    • D. abstract show();
    查看练习答案与解析

    答案:B 解析:A 有方法体,错误;B 无方法体,正确;C 关键字顺序错误;D 缺少返回类型。

14.以下程序段输出的结果是( )

java
public class Test {
    public static void main(String args[]) {
        String str = "ABCDE";
        str.substring(3);
        str.concat("XYZ");
        System.out.print(str);
    }
}
  • A. DE
  • B. DEXYZ
  • C. ABCDE
  • D. CDEXYZ
查看答案与解析

答案:C

解析: String 是不可变的,substring()concat() 方法都返回新字符串,不会修改原字符串

如果需要修改,应写 str = str.substring(3);str = str.concat("XYZ");


难度: ⭐⭐ 考点: #String不可变 #substring #concat

💡 学习锦囊

📖 相关公式与知识点:

  • String 不可变substring()concat() 等返回新对象,不修改原字符串
  • 修改 String:需要赋值 str = str.substring(3);

易错点

  • String 的所有修改方法都返回新对象,原对象不变
  • 必须赋值才能改变引用
🔄 举一反三
  1. 以下代码输出什么?String s = "hello"; s = s.toUpperCase(); System.out.println(s);
    查看练习答案与解析

    答案HELLO解析toUpperCase() 返回新字符串,赋值给 s 后 s 指向新对象 "HELLO"。

15.在下面程序中的括号中,如下哪些代码可以创建并启动线程?( )

java
class MyRunnable implements Runnable {
    public void run() {
        // ...
    }
}
  • A. new Runnable(MyRunnable).start()
  • B. new Thread(MyRunnable).run()
  • C. new Thread(new MyRunnable()).start()
  • D. new MyRunnable().start()
查看答案与解析

答案:C

解析: 创建并启动线程的正确方式:new Thread(Runnable对象).start()

  • A:Runnable 是接口,不能这样使用 ✗
  • B:调用 run() 只是普通方法调用,不会启动新线程 ✗
  • C:正确创建并启动线程 ✓
  • D:MyRunnable 没有 start() 方法 ✗

难度: ⭐⭐ 考点: #线程创建 #Runnable #start方法

💡 学习锦囊

📖 相关公式与知识点:

  • 线程创建new Thread(Runnable).start()
  • start() vs run()start() 启动新线程,run() 只是普通方法调用

易错点

  • 调用 run() 不会启动新线程
  • Runnable 对象没有 start() 方法,必须包装在 Thread
🔄 举一反三
  1. 继承 Thread 类创建线程的方式是什么?
    查看练习答案与解析
    java
    class MyThread extends Thread {
        public void run() { /* ... */ }
    }
    new MyThread().start();

    解析:继承 Thread 类并重写 run() 方法,直接调用 start() 启动线程。

16.如下程序输出( )

java
public class Test {
    public static void main(String[] args) {
        String s = "Java";
        StringBuilder buffer = new StringBuilder(s);
        change(s);
        System.out.println(s);
    }
    private static void change(String s) {
        s = s + " and HTML";
    }
}
  • A. Java
  • B. Java and HTML
  • C. and HTML
  • D. 什么都不显示
查看答案与解析

答案:A

解析: String 是不可变对象,且 Java 是值传递(引用类型的值是地址的副本)。

方法内的 s 是局部变量,重新赋值不影响 main 中的 s。输出 Java


难度: ⭐⭐⭐ 考点: #值传递 #String不可变

💡 学习锦囊

📖 相关公式与知识点:

  • Java 值传递:基本类型传值副本,引用类型传地址副本
  • String 不可变:修改 String 会创建新对象

易错点

  • Java 只有值传递,没有引用传递
  • String 在方法内重新赋值不影响外部变量
🔄 举一反三
  1. 如果将 change 方法的参数改为 StringBuilder,输出什么?
    查看练习答案与解析

    答案Java and HTML解析:StringBuilder 是可变对象,在方法内 s.append(" and HTML") 会修改原对象内容,外部变量能看到变化。

17.在使用 super 和 this 关键字时,以下描述正确的是( )

  • A. 在子类构造方法中使用 super() 显示调用父类的构造方法,super() 必须写在子类构造方法的第一行,否则编译不通过
  • B. this()super() 可以同时出现在一个构造函数中
  • C. super()this() 不一定要放在构造方法内第一行
  • D. this()super() 可以在 static 环境中使用,包括 static 方法和 static 语句块
查看答案与解析

答案:A

解析:

  • A 正确super() 必须是子类构造方法的第一条语句
  • B 错误:两者不能同时出现(都要求在第一行)
  • C 错误:都必须在构造方法的第一行
  • D 错误:都不能在 static 环境中使用

难度: ⭐⭐ 考点: #super #this #构造方法

💡 学习锦囊

📖 相关公式与知识点:

  • super():调用父类构造方法,必须在第一行
  • this():调用本类其他构造方法,必须在第一行
  • 互斥super()this() 不能同时出现

易错点

  • super()this() 必须在构造方法第一行
  • 两者不能同时出现在同一个构造方法中
🔄 举一反三
  1. 如果子类构造方法中没有显式调用 super(),会发生什么?
    查看练习答案与解析

    答案:编译器自动在第一行添加 super(),调用父类的无参构造方法 解析:如果父类没有无参构造方法,编译报错。

18.下面语句序列执行后,k 的值是什么?( )

java
int x = 6, y = 10, k;
switch (x % y) {
    case 0: k = x * y;
    case 6: k = x / y;
    case 12: k = x - y;
    default: k = x * y - x;
}
  • A. 60
  • B. 5
  • C. 0
  • D. 54
查看答案与解析

答案:D

解析:x % y = 6 % 10 = 6,匹配 case 6

关键:switch 语句中没有 break,会发生贯穿(fall-through)

case 6:  k = x / y = 6 / 10 = 0
case 12: k = x - y = 6 - 10 = -4
default: k = x * y - x = 6 * 10 - 6 = 54

最终 k = 54


难度: ⭐⭐⭐ 考点: #switch贯穿 #break #取模运算

💡 学习锦囊

📖 相关公式与知识点:

  • switch 贯穿:没有 break 会从匹配 case 执行到底
  • break:跳出 switch 语句

易错点

  • switch 语句忘记写 break 导致贯穿
  • 贯穿会从匹配的 case 开始执行所有后续 case 和 default
🔄 举一反三
  1. 如果每个 case 后都加上 break;,k 的值是什么?
    查看练习答案与解析

    答案:0 解析:匹配 case 6,k = 6 / 10 = 0,break 跳出 switch,k = 0。

19.下面关于缺省构造方法的描述中正确的是( )

  • A. 当类中没有定义任何构造方法时,Java 编译器将为这个类创建缺省构造方法
  • B. 缺省构造方法可以初始化其他方法中定义的变量
  • C. Java 编译器会为所有的类创建缺省构造方法
  • D. 如果在一个类中定义的构造方法都声明了参数,Java 编译器将为这个类创建一个缺省构造方法
查看答案与解析

答案:A

解析:

  • A 正确:当类中没有定义任何构造方法时,编译器自动生成无参缺省构造方法
  • B 错误:缺省构造方法只能初始化成员变量
  • C 错误:如果类中已定义了构造方法,编译器不会再创建
  • D 错误:已定义带参数的构造方法后,编译器不会再创建缺省构造方法

难度: ⭐⭐ 考点: #构造方法 #缺省构造方法

💡 学习锦囊

📖 相关公式与知识点:

  • 缺省构造方法:无参,方法体为空
  • 自动生成条件:类中没有定义任何构造方法时

易错点

  • 如果自定义了构造方法,编译器不再提供默认无参构造
🔄 举一反三
  1. 如果类中定义了 MyClass(int x) 但没有定义无参构造方法,new MyClass() 能编译吗?
    查看练习答案与解析

    答案:不能 解析:已定义有参构造方法后,编译器不再提供默认无参构造方法,需要手动添加。

20.下列哪个流类属于面向字符的输入流( )

  • A. BufferedWriter
  • B. FileInputStream
  • C. ObjectInputStream
  • D. InputStreamReader
查看答案与解析

答案:D

解析:

  • A:BufferedWriter输出流
  • B:FileInputStream字节流
  • C:ObjectInputStream字节流
  • D:InputStreamReader 是字节流到字符流的桥梁,属于面向字符的输入流

难度: ⭐⭐ 考点: #IO流 #字符流 #字节流

💡 学习锦囊

📖 相关公式与知识点:

  • 字节流:InputStream/OutputStream 及其子类
  • 字符流:Reader/Writer 及其子类
  • InputStreamReader:字节流 → 字符流的桥梁

易错点

  • FileInputStream 是字节流,不是字符流
  • InputStreamReader 是字符输入流
🔄 举一反三
  1. 下列哪个是面向字节的输出流?
    • A. FileReader
    • B. FileWriter
    • C. FileOutputStream
    • D. BufferedReader
    查看练习答案与解析

    答案:C 解析:A、D 是字符输入流;B 是字符输出流;C 是字节输出流。

二、程序阅读及填空题(共 20 空,每空 2 分,共 40 分)

1. 请在空格中填写以下程序执行的结果:

java
public class IdentifyMyParts {
    public static int x = 7;
    public int y = 3;
}

public class Test {
    public static void main(String[] args) {
        IdentifyMyParts a = new IdentifyMyParts();
        IdentifyMyParts b = new IdentifyMyParts();
        a.y = 5;
        b.y = 6;
        a.x = 1;
        b.x = 2;
        System.out.println("a.y = " + a.y);   // 屏幕输出为 (1)
        System.out.println("b.y = " + b.y);   // 屏幕输出为 (2)
        System.out.println("a.x = " + a.x);   // 屏幕输出为 (3)
        System.out.println("b.x = " + b.x);   // 屏幕输出为 (4)
    }
}
查看答案与解析

(1) 答案:a.y = 5

(2) 答案:b.y = 6

(3) 答案:a.x = 2

(4) 答案:b.x = 2

解析:

  • y实例变量(非 static),每个对象有独立副本:a.y = 5b.y = 6
  • x静态变量(static),所有对象共享同一份:最终 x = 2

难度: ⭐⭐ 考点: #静态变量 #实例变量 #static

💡 学习锦囊

📖 相关公式与知识点:

  • 静态变量 vs 实例变量:静态变量被所有实例共享,实例变量每个对象独立

易错点

  • 静态变量被所有实例共享,修改一个对象会影响所有对象
🔄 举一反三
  1. 以下代码输出什么?
    java
    public class Test {
        static int count = 0;
        int id;
        Test() { count++; id = count; }
        public static void main(String[] args) {
            Test t1 = new Test();
            Test t2 = new Test();
            Test t3 = new Test();
            System.out.println("t1.id=" + t1.id + ", t2.id=" + t2.id + ", count=" + count);
        }
    }
    查看练习答案与解析

    答案t1.id=1, t2.id=2, count=3解析:每次创建对象 count 自增并赋给 id。最终 count=3。

2. 请在空格中填写以下程序执行的结果:

java
public class java1 {
    public static void main(String[] args) {
        int arr[][] = {{34, 21, 45, 67, 20},
                       {23, 10, 3, 45, 76},
                       {22, 3, 79, 56, 50}};
        int i = 0;
        int j = 0;
        int min = arr[0][0];
        while (i < 3) {
            while ( (5) ) {
                if (arr[i][j] < min)
                    min = arr[i][j];
                j++;
            }
            (6) ;
            (7) ;
        }
        System.out.println("The min:" + min);
    }
}
查看答案与解析

(5) 答案:j < 5

(6) 答案:i++

(7) 答案:j = 0

解析: 程序功能:遍历二维数组找最小值。

  • (5) 内层循环控制列索引,每行有 5 列,条件为 j < 5
  • (6) 行索引加 1:i++
  • (7) 列索引重置为 0:j = 0

难度: ⭐⭐ 考点: #二维数组 #数组遍历 #求最小值

💡 学习锦囊

📖 相关公式与知识点:

  • 二维数组遍历:外层循环行,内层循环列,注意索引重置

易错点

  • 内层循环结束后必须重置列索引 j = 0
  • 行索引 i++ 不能遗漏
🔄 举一反三
  1. 如何修改程序使其求最大值?
    查看练习答案与解析

    if (arr[i][j] < min) 改为 if (arr[i][j] > max),并将初始值设为 int max = arr[0][0]解析:只需将比较方向反转即可。

3. 写出下列程序的输出结果:

java
class Exam31 {
    public static void main(String[] args) {
        int i = 1, j = 2, k = 3;
        boolean b = -i > 1 && j++ < 2 && k-- < 3;
        b = ++i > 1 || j-- < 2 && --k > 3;
        b = ++i > 1 | j-- < 2 && --k > 3;
        System.out.println("i=" + i);   // 屏幕输出为 (8)
        System.out.println("j=" + j);   // 屏幕输出为 (9)
        System.out.println("k=" + k);   // 屏幕输出为 (10)
    }
}
查看答案与解析

(8) 答案:i=3

(9) 答案:j=1

(10) 答案:k=3

解析:

第一行boolean b = -i > 1 && j++ < 2 && k-- < 3;

  • -i = -1,-1 > 1 为 false,&& 短路,j++ 和 k-- 不执行
  • i=1, j=2, k=3

第二行b = ++i > 1 || j-- < 2 && --k > 3;

  • ++i → i=2,2 > 1 为 true,|| 短路,j-- 和 --k 不执行
  • i=2, j=2, k=3

第三行b = ++i > 1 | j-- < 2 && --k > 3;

  • ++i → i=3,3 > 1 为 true
  • |非短路或,右边也要计算
  • j-- < 2:j=2,2 < 2 为 false,然后 j=1
  • false && ... 短路,--k 不执行
  • i=3, j=1, k=3

难度: ⭐⭐⭐ 考点: #短路逻辑 #非短路或 #自增自减

💡 学习锦囊

📖 相关公式与知识点:

  • 短路逻辑运算符&&|| 会短路
  • 非短路逻辑运算符&| 不会短路,两边都计算

易错点

  • | 是非短路或,两边都会计算;|| 是短路或
  • && 短路:左边为 false 不执行右边
🔄 举一反三
  1. 以下代码输出什么?
    java
    int a = 5, b = 10;
    boolean r = (a > 3) | (b++ > 10);
    System.out.println("b=" + b);
    查看练习答案与解析

    答案b=11解析| 是非短路或,即使左边为 true,右边 b++ > 10 仍然执行,b 从 10 变为 11。

4. 请写出以下程序运行结果:

java
public class Main {
    public static void main(String[] args) {
        String s = "hello";
        try {
            s = s + "world";
            s.toUpperCase();
            String[] a = s.split("o");
            System.out.println(a.length);    // 屏幕输出为 (11)
        } catch (Exception e) {
        } finally {
            System.out.print(s);             // 屏幕输出为 (12)
        }
    }
}
查看答案与解析

(11) 答案:3

(12) 答案:helloworld

解析:

java
s = s + "world";      // s = "helloworld"
s.toUpperCase();       // 返回新字符串,但未赋值给 s,s 不变
String[] a = s.split("o");  // 按 "o" 分割 "helloworld"

分割结果:a = ["hell", "w", "rld"]a.length = 3

finally 块输出 s,s 仍为 "helloworld"


难度: ⭐⭐⭐ 考点: #String操作 #split #toUpperCase

💡 学习锦囊

📖 相关公式与知识点:

  • String 不可变toUpperCase() 返回新对象,不修改原字符串
  • split() 方法:按分隔符分割字符串,返回数组

易错点

  • s.toUpperCase() 不会修改 s,必须 s = s.toUpperCase() 才行
  • split("o") 分割后,分隔符本身不出现在结果中
🔄 举一反三
  1. "a,b,,c".split(",") 的结果数组长度是多少?
    查看练习答案与解析

    答案:4 解析:分割为 ["a", "b", "", "c"],长度为 4。注意空字符串也会作为元素。

5. 以下程序为类 Animal、Bird、Parrot 和 Test 的代码,请将程序填充完整,并填写输出结果。包结构为:com.an 中有 Animal 类;com.bd 中有 Bird、Parrot、Test 类。

java
// com.an 包
package com.an;
public (13) class Animal {
    (14) String color;
    public abstract void sound();
    public Animal() {
        color = "";
        System.out.println("动物");
    }
}

// com.bd 包
package com.bd;
public class Bird (15) Animal {
    public Bird() {
        color = "绿色";
        System.out.println("鸟");
    }
    public void sound() {
        System.out.println("鸟叫声");
    }
    public void sound(String msg) {
        System.out.println("鸟发出的叫声:" + msg);
    }
}

public class Parrot extends Bird {
    public Parrot() {
        System.out.println("鹦鹉");
    }
    public void sound() {
        (16) ;   // 调用父类的方法 sound()
    }
}

public class Test {
    public static void main(String[] args) {
        Parrot p = new Parrot();
        p.sound();
    }
}
查看答案与解析

(13) 答案:abstract

(14) 答案:protected

(15) 答案:extends

(16) 答案:super.sound()

解析:

  • (13) Animal 类有抽象方法 sound(),必须声明为 abstract 类。
  • (14) color 需要被不同包的子类 Bird 访问,必须用 protected 修饰。
  • (15) Bird 继承 Animal,使用 extends 关键字。
  • (16) 子类 Parrot 调用父类 Bird 的 sound() 方法,使用 super.sound()

程序运行输出:

动物

鹦鹉
鸟叫声

构造方法调用链:Parrot() → Bird() → Animal()(输出"动物")→ Bird()体(输出"鸟")→ Parrot()体(输出"鹦鹉")→ p.sound() → super.sound()(输出"鸟叫声")


难度: ⭐⭐⭐ 考点: #抽象类 #继承 #protected #super #构造方法调用链

💡 学习锦囊

📖 相关公式与知识点:

  • 抽象类:含抽象方法的类必须声明为 abstract
  • protected 访问权限:允许跨包的子类访问
  • 构造方法调用链:创建子类对象时,先调用父类构造方法

易错点

  • 不同包的子类访问父类成员需要 protectedpublic 权限
  • 构造方法调用顺序:父类先于子类
🔄 举一反三
  1. 如果将 color 改为 private,Bird 类能否访问?
    查看练习答案与解析

    答案:不能 解析:private 成员只能在本类中访问,即使是子类也不能直接访问。

6. 在横线处填上合适的语句。

java
// MyException 为用户自定义异常类
public class MyException extends Exception {
}

class Person {
    // 在下行空白处写出声明方法可能抛出 MyException 异常的语句
    public void check(String strage) (17) {
        int age = Integer.parseInt(strage);
        if (age < 0) {
            /* 在下行空白处填上抛出 MyException 异常对象的语句,
               异常信息描述为"年龄不能为负数!" */
            (18) ;
        }
    }
}
查看答案与解析

(17) 答案:throws MyException

(18) 答案:throw new MyException("年龄不能为负数!")

解析:

  • (17) 方法声明可能抛出的异常,使用 throws 关键字(在方法签名后)。
  • (18) 实际抛出异常对象,使用 throw new 关键字。

注意区分:

  • throws:声明异常(在方法签名中)
  • throw:抛出异常(在方法体中)

难度: ⭐⭐ 考点: #异常抛出 #throws #throw

💡 学习锦囊

📖 相关公式与知识点:

  • throws:声明异常(在方法签名中)
  • throw:抛出异常(在方法体中)

易错点

  • throws 在方法签名中声明异常,throw 在方法体中抛出异常对象
  • throw 后面跟异常对象,throws 后面跟异常类名
🔄 举一反三
  1. 如何在调用 check 方法时处理异常?
    查看练习答案与解析
    java
    try {
        person.check("-5");
    } catch (MyException e) {
        System.out.println(e.getMessage());
    }

    解析:使用 try-catch 捕获 MyException。

7. 如果一个整数 a 能被数 b 整除,则 b 是 a 的因子。下面是一个 Java 程序,它的功能是求给定整数 n 的所有因子的和 sum,请将程序补充完整。

java
public class Test {
    public static void main(String args[]) {
        int n = 6, sum = 0;
        for (int k = 1; (19) ; k++) {
            if ( (20) )
                sum += k;
        }
        System.out.println(sum);
    }
}
查看答案与解析

(19) 答案:k <= n

(20) 答案:n % k == 0

解析:

  • (19) 循环范围从 1 到 n,条件为 k <= n
  • (20) 判断 k 是否为 n 的因子:n % k == 0

当 n=6 时:因子为 1, 2, 3, 6,sum = 12。


难度: ⭐⭐ 考点: #因子 #取模运算 #循环

💡 学习锦囊

📖 相关公式与知识点:

  • 因子:如果 n % k == 0,则 k 是 n 的因子
  • 取模运算n % k 求 n 除以 k 的余数

易错点

  • 循环条件是 k <= n,不是 k < n(n 本身也是因子)
  • 判断因子用 n % k == 0,不是 k % n == 0
🔄 举一反三
  1. 求 n=12 的所有因子之和。
    查看练习答案与解析

    答案:28 解析:12 的因子为 1, 2, 3, 4, 6, 12,sum = 28。

三、编程题(共 3 题,每题 10 分,共 30 分)

1. 定义基类 Point(点)和派生类 Circle(圆),求圆的周长。Point 类有两个私有的数据成员 float x, y;Circle 类新增一个私有的数据成员半径 float r 和一个公有的求周长的函数 getCircumference();请编写 Point 和 Circle 类以及测试类。

查看答案与解析

答案:

java
class Point {
    private float x;
    private float y;

    public Point(float x, float y) {
        this.x = x;
        this.y = y;
    }

    public float getX() {
        return x;
    }

    public float getY() {
        return y;
    }
}

class Circle extends Point {
    private float r;

    public Circle(float x, float y, float r) {
        super(x, y);
        this.r = r;
    }

    public float getCircumference() {
        return 2 * 3.14159f * r;
    }
}

public class Test {
    public static void main(String[] args) {
        Circle c = new Circle(0, 0, 5);
        System.out.println("圆心:(" + c.getX() + ", " + c.getY() + ")");
        System.out.println("半径:" + 5);
        System.out.println("周长:" + c.getCircumference());
    }
}

运行结果:

圆心:(0.0, 0.0)
半径:5
周长:31.4159

解析:

第一步:设计 Point 类 - 两个私有成员 float x, y 表示坐标,构造方法初始化,提供 getter 方法。

第二步:设计 Circle 类 - 继承 Point 类,新增私有成员 float r,构造方法调用 super(x, y)getCircumference() 计算周长 $C = 2\pi r$

第三步:测试类 - 创建 Circle 对象,调用 getCircumference() 输出周长。


难度: ⭐⭐⭐ 考点: #继承 #super #圆的周长

💡 学习锦囊

📖 相关公式与知识点:

  • 圆的周长$C = 2\pi r$
  • 继承:子类使用 extends 继承父类,super() 调用父类构造方法

易错点

  • 子类构造方法必须调用 super(),且必须是第一条语句
  • 父类的私有成员子类不能直接访问
🔄 举一反三
  1. 在此基础上,为 Circle 类添加求面积的方法 getArea()
    查看练习答案与解析
    java
    public float getArea() {
        return 3.14159f * r * r;
    }

    解析:圆面积公式 $S = \pi r^2$,当 r=5 时,面积约为 78.53975。

2. 编写一个应用程序实现文件的拷贝,源文件(SourceFile.txt)及目标文件(TargetFile.txt)通过命令行参数得到。

查看答案与解析

答案:

java
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileCopy {
    public static void main(String[] args) {
        if (args.length < 2) {
            System.out.println("用法:java FileCopy <源文件> <目标文件>");
            return;
        }
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream(args[0]);
            fos = new FileOutputStream(args[1]);
            int ch;
            while ((ch = fis.read()) != -1) {
                fos.write(ch);
            }
            System.out.println("文件拷贝完成!");
        } catch (IOException e) {
            System.out.println("文件操作出错:" + e.getMessage());
        } finally {
            try {
                if (fis != null) fis.close();
                if (fos != null) fos.close();
            } catch (IOException e) {
                System.out.println("关闭流出错:" + e.getMessage());
            }
        }
    }
}

解析:

第一步:获取命令行参数 - args[0] 为源文件路径,args[1] 为目标文件路径

第二步:创建输入输出流 - FileInputStream 读取源文件,FileOutputStream 写入目标文件

第三步:循环读写 - fis.read() 逐字节读取,fos.write(ch) 写入

第四步:关闭流 - 在 finally 块中关闭流,确保资源释放


难度: ⭐⭐⭐ 考点: #文件IO #FileInputStream #FileOutputStream #命令行参数

💡 学习锦囊

📖 相关公式与知识点:

  • 文件拷贝FileInputStream + FileOutputStream 逐字节读写
  • 命令行参数main(String[] args) 中的 args 接收命令行参数
  • 异常处理:try-catch-finally 确保流关闭

易错点

  • 文件操作后必须在 finally 中关闭流
  • 关闭流前要检查是否为 null
🔄 举一反三
  1. 使用 BufferedReader 和 BufferedWriter 实现文件拷贝。
    查看练习答案与解析
    java
    import java.io.*;
    public class FileCopy2 {
        public static void main(String[] args) throws IOException {
            BufferedReader br = new BufferedReader(new FileReader(args[0]));
            BufferedWriter bw = new BufferedWriter(new FileWriter(args[1]));
            String line;
            while ((line = br.readLine()) != null) {
                bw.write(line);
                bw.newLine();
            }
            br.close();
            bw.close();
        }
    }

    解析:BufferedReader 提供 readLine() 按行读取,BufferedWriter 提供 write()newLine() 按行写入。

3. 编写一个完整的 Java Application 程序。包含类 Shape、类 Oval、类 Main,具体要求如下:

(1)编写一个抽象类 Shape 表示形状对象,包含以下成员:

  • 属性:double 型常量 PI,其值为 3.1415926;
  • 方法:包含 double area()double perimeter() 两个抽象方法;

(2)编写一个 Shape 类的子类 Oval,表示椭圆对象,包含以下成员:

  • 属性:double 型私有成员变量 a,表示长轴半径;double 型私有成员变量 b,表示短轴半径;
  • 方法:构造方法 Oval(double a, double b),用参数设置椭圆的长轴半径和短轴半径;构造方法 Oval(),将椭圆的长轴半径和短轴半径都初始化为 0;成员方法 double area(),重写 Shape 类中的 area 方法,返回椭圆的面积;成员方法 double perimeter(),重写 Shape 类中的 perimeter 方法,返回椭圆的周长;方法 public String toString(),将当前的椭圆对象转换成字符串形式,例如长轴半径为 10.0,短轴半径为 5,返回字符串 "Oval(a:10.0, b:5.0)"

(3)编写公共类 Main,实现如下功能: 1)创建一个长轴半径为 8.0,短轴半径为 6.0 的椭圆对象; 2)分别用 area 和 perimeter 方法,求出以上椭圆的面积和周长并输出,输出过程中要求使用到 toString 方法。

查看答案与解析

答案:

java
abstract class Shape {
    final double PI = 3.1415926;

    abstract double area();

    abstract double perimeter();
}

class Oval extends Shape {
    private double a;
    private double b;

    public Oval(double a, double b) {
        this.a = a;
        this.b = b;
    }

    public Oval() {
        this.a = 0;
        this.b = 0;
    }

    @Override
    double area() {
        return PI * a * b;
    }

    @Override
    double perimeter() {
        return 2 * PI * Math.sqrt((a * a + b * b) / 2);
    }

    @Override
    public String toString() {
        return "Oval(a:" + a + ", b:" + b + ")";
    }
}

public class Main {
    public static void main(String[] args) {
        Oval oval = new Oval(8.0, 6.0);
        System.out.println(oval.toString() + " 的面积:" + oval.area());
        System.out.println(oval.toString() + " 的周长:" + oval.perimeter());
    }
}

运行结果:

Oval(a:8.0, b:6.0) 的面积:150.7964448
Oval(a:8.0, b:6.0) 的周长:44.424808439447055

解析:

第一步:设计 Shape 抽象类 - 定义常量 PI = 3.1415926,声明两个抽象方法 area()perimeter()

第二步:设计 Oval 类 - 私有成员 a(长轴半径)和 b(短轴半径),两个构造方法,椭圆面积公式 $S = \pi \times a \times b$,椭圆周长近似公式 $P \approx 2\pi\sqrt{\frac{a^2 + b^2}{2}}$

第三步:Main 类测试 - 创建 Oval(8.0, 6.0) 对象,使用 toString() 输出对象信息,调用 area()perimeter() 计算面积和周长


难度: ⭐⭐⭐ 考点: #抽象类 #方法重写 #椭圆面积 #椭圆周长 #toString

💡 学习锦囊

📖 相关公式与知识点:

  • 椭圆面积$S = \pi \times a \times b$(a 为长轴半径,b 为短轴半径)
  • 椭圆周长近似$P \approx 2\pi\sqrt{\frac{a^2 + b^2}{2}}$
  • 抽象类:含抽象方法的类必须声明为 abstract,子类必须实现所有抽象方法
  • toString():Object 类的方法,子类重写以返回对象的字符串表示

易错点

  • 子类构造方法必须调用 super(),且必须是第一条语句
  • 抽象类不能实例化,但可以有构造方法供子类调用
  • toString() 方法必须用 public 修饰
  • final 常量在声明时必须初始化
  • 椭圆周长没有精确的初等公式,常用近似公式
🔄 举一反三
  1. 如果要添加一个 Circle 类(圆是椭圆的特殊情况,a=b=r),如何实现?
    查看练习答案与解析
    java
    class Circle extends Oval {
        public Circle(double r) {
            super(r, r);
        }
    }

    解析:圆是长轴半径等于短轴半径的椭圆,继承 Oval 并在构造方法中传入相同的 r 值即可。

你正在阅读的是会员专属文档,💕 限时特惠进行中
你尚未登录,目前新用户可获3天体验会员,去登录