Java试卷


1. 多项选择题

(1) byte 类型的范围是:( )

  1. -128 到 127
  2. \((-2^8) - 1\)\(2^8\)
  3. -255 到 256
  4. 取决于 Java 虚拟机

答案: a
解释: byte 类型的范围是 -128 到 127,占用 1 个字节(8 位),这是固定的,与虚拟机无关。


(2) 当调用 System.out.println(4 | 010); 时,将会输出什么?( )

  1. 14
  2. 0
  3. 6
  4. 12

答案: d
解释: 4 | 010 是按位或操作。010 是八进制,等于 8。二进制中的 410081000,按位或结果为 1100,即 12。


(3) 给定以下类定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class A {
public int x;
private int y;
class B {
protected void method1() {
}
class C {
private void method2() {
}
}
}
}

class D extends A {
public float z;
}

method2() 可以访问下列哪些成员?(3个)( )

  1. A 类中的变量 x
  2. A 类中的变量 y
  3. B 类中的方法 method1()
  4. D 类中的变量 z

答案: a, c
解释: method2()C 类中的方法,CB 的内部类,而 BA 的内部类。method2() 可以访问外部类的 public 成员(如 x),但不能访问 private 成员(如 y)。同样,method2() 可以访问 protected 的方法 method1()


(4) 给定以下接口定义:

1
2
3
4
interface A {
int method1(int i);
int method2(int j);
}

哪个类正确实现了该接口?( )

1
2
3
4
class B implements A {
int method1() { }
int method2() { }
}
1
2
3
4
class B {
int method1(int i) { }
int method2(int j) { }
}
1
2
3
4
class B implements A {
int method1(int i) { }
int method2(int j) { }
}
1
2
3
4
class B extends A {
int method1(int i) { }
int method2(int j) { }
}
1
2
3
4
class B implements A {
int method2(int j) { }
int method1(int i) { }
}

答案: c, e
解释: 选项 c 和 e 都正确实现了接口 A。类 B 实现了接口的两个方法,且方法签名正确。a 选项缺少参数,b 和 d 选项没有实现接口。


(5) 当运行以下代码片段时,会输出什么?( )

1
2
3
4
5
6
7
8
9
10
11
12
13
Boolean b1 = new Boolean(true);
Boolean b2 = new Boolean(true);

if (b1 == b2)
if (b1.equals(b2))
System.out.println("a");
else
System.out.println("b");
else
if (b1.equals(b2))
System.out.println("c");
else
System.out.println("d");
  1. a
  2. b
  3. c
  4. d

答案: c
解释: b1b2 是不同的对象,== 比较的是对象的引用,因此 b1 == b2false。但 b1.equals(b2)true,因此输出 c


(6) 关于以下语句,哪个是正确的?( )

1
String[][] s = new String[10][];
  1. 该语句包含错误
  2. s 是一个 10 行 10 列的数组
  3. s 是一个包含 10 个数组的数组
  4. s 的元素值是 ""
  5. 在使用该数组前必须初始化

答案: c
解释: s 是一个二维数组,但每一行的列数可以不同,因此它实际上是一个包含 10 个数组的数组。


(7) 编译和运行以下类时会发生什么?( )

1
2
3
4
5
6
7
class Test {
static int myArg = 1;
public static void main(String[] args) {
int myArg;
System.out.println(myArg);
}
}
  1. 输出结果为 0
  2. 输出结果为 1
  3. 无法成功编译,因为局部变量名称与静态变量名称相同
  4. 无法成功编译,因为局部变量在使用前必须初始化

答案: d
解释: 局部变量 myArg 在输出前没有被初始化,因此会导致编译错误。


(8) 关于独立应用程序中的 main() 方法,哪个是正确的?( )

  1. public static void main()
  2. public static void main(String[] string)
  3. public static void main(String args)
  4. static public int main(String[] args)
  5. static void main(String[] args)

答案: b
解释: main 方法的正确签名是 public static void main(String[] args),它接受一个字符串数组作为参数。


(9) 给定以下类 Cycle,命令行如下:

1
java  Cycle  one  two

输出结果是什么?( )

1
2
3
public static void main(String bicycle[]) {
System.out.println(bicycle[0]);
}
  1. Cycle
  2. one
  3. two
  4. 无输出

答案: b
解释: 命令行参数 onetwo 被传递给 bicycle 数组,因此 bicycle[0]one


(10) 若要输出 "running",应在 //A 处放入什么?( )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class RunTest implements Runnable {
public static void main(String[] args) {
RunTest rt = new RunTest();
Thread t =new Thread(rt);
//A
}
public void run() {
System.out.println("running");
}
void go() {
start(1);
}
void start(int i) {
}
}
  1. System.out.println("running");
  2. rt.start();
  3. rt.go();
  4. rt.start(1);

答案: c
在这个问题中,代码设计的关键点是理解 Runnable 接口和 Thread 的关系,以及方法调用的逻辑。

首先,RunTest 类实现了 Runnable 接口,因此它必须提供一个 run() 方法。在 run() 方法中,当 Thread 对象的 start() 方法被调用时,它会自动执行 run() 方法中的逻辑,在这里是 System.out.println("running");

看一下 main() 方法:

1
2
3
4
5
public static void main(String[] args) {
RunTest rt = new RunTest();
Thread t = new Thread(rt);
//A
}

//A 处,你需要添加一些代码来启动线程,使得线程执行 run() 方法,输出 "running"。

正确的答案是 c) rt.go();,因为 go() 方法会调用 start(1) 方法,尽管 start(1) 没有做任何事,但是 go() 方法是必要的入口。而关键在于,当创建了 Thread 对象 t 时,还需要通过调用 t.start() 来启动线程,执行 run() 方法。

实际的执行流程是:

  1. rt.go() 被调用;
  2. t.start() 应该被调用,这会触发 run() 方法中的代码,输出 "running"。

因此正确的解释应该是:选择 c,并且你需要调用的是 go() 方法。

11. 编译以下语句时,哪个选项是正确的?(3)( )

1
2
float f = 3.2;
int i = f;
  1. 两行都无法成功编译;
  2. 两行都可以成功编译,i 的值为 3;
  3. 如果第二行修改为 int i = (byte)f;,则可以成功编译;
  4. 如果第一行修改为 float f = 3.2F;,则可以成功编译。

答案: d
解释: 在 Java 中,浮点数默认是 double 类型。因此第一行需要将 3.2 明确为 float 类型,使用 3.2F。第二行尝试将 float 类型赋值给 int 会报错,因为无法隐式转换,需要进行强制类型转换。


12. 考虑以下语句,哪个选项是正确的?( )

1
if (5 & 7 > 0 && 5 | 2) System.out.println("true");
  1. 无法成功编译;
  2. 可以成功编译并运行,无输出结果;
  3. 可以编译并运行,输出结果为 "true"。

答案: a
解释: 表达式中 5 & 75 | 2 需要是布尔值,而位操作符 &| 不能直接用于条件判断,需要使用逻辑运算符。


13. 以下哪些不是 Java 关键字?(2)( )

  1. FALSE
  2. sizeof
  3. super
  4. void

答案: a, b
解释: FALSEsizeof 都不是 Java 的关键字,Java 中布尔值是 truefalse,而 sizeof 是 C/C++ 中的关键字,不存在于 Java 中。supervoid 是 Java 的保留关键字。


14. 关于继承,哪个选项是正确的?(2)( )

  1. 只允许单继承;
  2. 一个类只能实现一个接口;
  3. 一个类不能同时继承一个类并实现一个接口;
  4. 单继承使代码更加稳定。

答案: a, d
解释: Java 只允许类的单继承,但允许一个类实现多个接口。单继承通常被认为有助于减少复杂性,增强代码的稳定性。


15. 哪个选项是正确的?(3)( )

  1. 实例变量是类的成员;
  2. 实例变量是用 static 定义的;
  3. 方法中的局部变量在方法被调用时创建;
  4. 局部变量必须在使用前初始化。

答案: a, c, d
解释: 实例变量是类的成员,而 static 定义的是静态变量。局部变量在方法调用时创建,并且必须在使用前初始化。


16. 关于垃圾回收 (Garbage Collection, GC),哪个选项是正确的?( )

  1. 程序员必须编写程序释放内存;
  2. 垃圾回收器会检查内存并释放它;
  3. GC 可以被调用并立即释放内存;
  4. GC 可以在预期时间内释放内存。

答案: b
解释: 垃圾回收器自动检查并释放未使用的内存,程序员不需要手动管理内存分配和释放。GC 无法确保在特定的时间内释放内存,并且调用 System.gc() 只是建议 GC 运行,不能保证立即执行。


17. 哪个选项不正确?( )

  1. float f = 11.1;
  2. double d = 5.3E12;
  3. double d = 3.14159;
  4. double d = 3.14D;

答案: a
解释: 在 Java 中,浮点数默认是 double 类型。因此,如果要将 11.1 分配给 float,需要将其写为 11.1F,否则会导致编译错误。


18. Runnable 接口的方法是哪个?( )

  1. run
  2. start
  3. yield
  4. stop

答案: a
解释: Runnable 接口只有一个方法 run(),用于定义线程执行的任务。start()Thread 类的方法,而 yield()stop() 也不属于 Runnable 接口。


19. 执行以下代码时,输出是什么?( )

1
2
3
4
5
6
public class MyClass {
static int i;
public static void main(String argv[]) {
System.out.println(i);
}
}
  1. 错误,变量 i 可能未初始化;
  2. null
  3. 1
  4. 0

答案: d
解释: 静态变量 iint 类型的,在没有显式初始化时,默认值为 0


20. 哪些选项是正确的?(2)( )

  1. 默认构造函数有返回类型;
  2. 默认构造函数有参数;
  3. 默认构造函数不能接受参数;
  4. 当创建了其他构造函数后,默认构造函数不能被创建。

答案: c, d
解释: 默认构造函数没有返回类型,并且默认构造函数不能接受参数。一旦程序员显式定义了其他构造函数,默认的无参构造函数就不再自动生成。

判断题(每题1分,共10分)

  1. Java 的原始数据类型依赖于平台。( )
    • 答案: 错误
    • 解释: Java 是平台无关的编程语言,其原始数据类型(如 int, float, double 等)在所有平台上都具有相同的大小和范围。因此,Java 的原始数据类型不依赖于具体的平台。
  2. 含有抽象方法的类必须定义为抽象类。( )
    • 答案: 正确
    • 解释: 在 Java 中,如果一个类包含至少一个抽象方法,则该类必须被定义为抽象类。否则,编译器会报错。
  3. 静态方法不能访问 "this" 变量。( )
    • 答案: 正确
    • 解释: 静态方法是属于类的,而不是某个对象,因此在静态方法中没有 this 关键词,因为 this 指代的是当前对象的引用。
  4. InputStreamFileReader 的父类。( )
    • 答案: 错误
    • 解释: InputStream 是字节流的基类,而 FileReader 是字符流的类。FileReader 的父类是 Reader,而不是 InputStream
  5. 构造函数可以有返回类型。( )
    • 答案: 错误
    • 解释: 构造函数不能有返回类型。如果给构造函数添加了返回类型,它就不再是构造函数,而是普通方法。
  6. Runnable 接口只包含一个 run() 方法,且该方法必须被实现。( )
    • 答案: 正确
    • 解释: Runnable 是一个函数式接口,它只定义了一个方法 run(),需要由实现该接口的类来具体实现。
  7. 一个组件可以使用多个事件监听器。( )
    • 答案: 正确
    • 解释: 在 Java 中,一个组件可以同时注册多个事件监听器来处理不同类型的事件或同一事件的不同处理。
  8. 构造函数不能被定义为私有的。( )
    • 答案: 错误
    • 解释: 构造函数可以被定义为私有的,通常用于单例模式,确保类的实例只能在类内部创建。
  9. 接口可以有构造函数。( )
    • 答案: 错误
    • 解释: 接口不能有构造函数,因为接口本质上不能被实例化,构造函数是用于创建对象的。
  10. 接口中的成员变量是静态和最终的。( )
    • 答案: 正确
    • 解释: Java 接口中的成员变量默认是 publicstaticfinal,这意味着它们是常量,不能被修改。

三.程序分析题(每题4分,共20分)

1. 请写出 testing() 方法被调用时的输出结果

1
2
3
4
5
6
7
8
9
10
11
void testing() {
one:
for (int i = 0; i < 3; i++) {
three:
for (int j = 10; j < 30; j += 10) {
System.out.println(i + j);
if (i > 2)
continue one;
}
}
}

输出结果:

1
2
3
4
5
6
10
20
11
21
12
22

解释:

  • 外层循环 i 从 0 到 2。
  • 内层循环 j 从 10 开始,步长为 10,直到小于 30,因此 j 取值为 10 和 20。
  • 每次都会输出 i + j 的结果,当 i > 2 时,继续外层循环,但 i 最大值为 2,不会触发 continue one

2. 请写出以下代码的输出结果

1
2
3
4
5
6
7
int output = 20;
boolean b1 = false;
if ((b1 == true) && ((output += 10) == 30)) {
System.out.println("We are equal: " + output);
} else {
System.out.println("Not equal: " + output);
}

输出结果:

1
Not equal: 20

解释:

  • b1false,由于 && 的短路特性,右边的表达式 (output += 10) 不会被执行,output 保持为 20。
  • 因此,else 块被执行,输出 "Not equal: 20"。

3. 请写出以下代码的输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Vehicle {
public void drive() {
System.out.println("Vehicle: drive");
}
}

class Car extends Vehicle {
public void drive() {
System.out.println("Car: drive");
}
}

public class Test {
public static void main(String[] args) {
Vehicle v;
Car c;
v = new Vehicle();
c = new Car();
v.drive();
c.drive();
v = c;
v.drive();
}
}

输出结果:

1
2
3
Vehicle: drive
Car: drive
Car: drive

解释:

  • vVehicle 的实例,第一次调用 v.drive() 输出 "Vehicle: drive"。
  • cCar 的实例,调用 c.drive() 输出 "Car: drive"。
  • v = c 后,v 指向了 Car 实例,调用 v.drive() 也是输出 "Car: drive"。

4. 请写出以下代码的输出结果

1
2
3
4
5
6
7
8
9
10
11
12
int i = 9;
switch (i) {
default:
System.out.println("default");
case 0:
System.out.println("zero");
break;
case 1:
System.out.println("one");
case 2:
System.out.println("two");
}

输出结果:

1
2
default
zero

解释:

  • i = 9,没有匹配到任何 case,因此执行 default
  • default 执行后,继续执行 case 0,输出 "zero" 后遇到 break,跳出 switch 结构。

5. 请写出以下代码的输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Mammal {
Mammal() {
System.out.println("Four");
}

public void ears() {
System.out.println("Two");
}
}

class Dog extends Mammal {
Dog() {
super.ears();
System.out.println("Three");
}
}

public class Scottie extends Dog {
public static void main(String[] args) {
System.out.println("One");
Scottie h = new Scottie();
}
}

输出结果:

1
2
3
4
One
Two
Three
Four

解释:

  • 首先输出 "One"。
  • Scottie 的构造方法隐式调用了 Dog 的构造函数,Dog 的构造函数调用了 Mammal 类中的 ears() 方法,输出 "Two"。
  • 然后继续执行 Dog 的构造函数,输出 "Three"。
  • 最后,Mammal 的构造函数被调用,输出 "Four"。

四.简答题(每题6分,共30分)

1. 写出 Java 的特点

Java 作为一种广泛使用的编程语言,具有以下几个特点:

  • 跨平台性:Java 具有“编写一次,到处运行”的特点,因为 Java 程序被编译成字节码后,可以在任何支持 Java 虚拟机(JVM)的操作系统上运行。
  • 面向对象编程:Java 是一种面向对象的编程语言,支持封装、继承和多态,易于构建模块化和可维护的程序。
  • 内存管理:Java 提供自动垃圾回收机制(Garbage Collection, GC),开发者无需手动释放内存,减少内存泄漏的风险。
  • 丰富的标准库:Java 拥有庞大的标准库,提供了大量的实用类库,帮助开发者快速实现各种功能。
  • 安全性:Java 在设计时非常注重安全性,提供了多种机制来防止恶意代码执行,例如类加载器和字节码验证器。
  • 多线程支持:Java 通过 java.lang.Thread 类和 Runnable 接口提供了对多线程编程的支持,易于开发并发程序。

2. 描述创建线程的两种方式

在 Java 中,创建线程有两种主要方式:

  • 继承 Thread

    1. 定义一个类继承自 Thread 类。
    2. 重写 run() 方法,在 run() 方法中编写线程的任务。
    3. 创建该类的实例并调用 start() 方法启动线程。

    示例代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class MyThread extends Thread {
    public void run() {
    System.out.println("Thread is running");
    }
    }
    public class Main {
    public static void main(String[] args) {
    MyThread t = new MyThread();
    t.start();
    }
    }
  • 实现 Runnable 接口

    1. 定义一个类实现 Runnable 接口。
    2. 实现 run() 方法,在 run() 方法中编写线程的任务。
    3. 创建 Thread 对象并将 Runnable 实现类的实例传入,然后调用 start() 方法启动线程。

    示例代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class MyRunnable implements Runnable {
    public void run() {
    System.out.println("Runnable thread is running");
    }
    }
    public class Main {
    public static void main(String[] args) {
    MyRunnable r = new MyRunnable();
    Thread t = new Thread(r);
    t.start();
    }
    }

3. 描述面向对象编程的特点

面向对象编程(OOP)有以下主要特点:

  • 封装(Encapsulation):将数据和操作数据的方法封装在类中,隐藏内部实现细节,通过公共接口与外部交互,增强代码的安全性和可维护性。
  • 继承(Inheritance):通过继承机制,可以在一个类的基础上创建新的类,新类可以继承父类的属性和方法,从而实现代码复用,降低开发成本。
  • 多态(Polymorphism):同一个方法在不同对象中表现出不同的行为,可以通过父类引用指向子类对象,从而实现运行时的动态绑定,提高程序的灵活性和可扩展性。
  • 抽象(Abstraction):将复杂的现实问题抽象为程序中的类和对象,只关注对象的行为和状态,而隐藏不必要的实现细节,简化复杂性。

4. 描述如何使用 Socket 编写程序

Socket 编程用于网络通信,Java 提供了 SocketServerSocket 类来实现客户端与服务器之间的通信。编写基于 Socket 的程序通常包含以下步骤:

  • 服务器端

    1. 创建 ServerSocket 对象并绑定到指定端口。
    2. 调用 accept() 方法,等待客户端连接。
    3. 一旦连接建立,获取 Socket 对象,使用输入输出流进行数据传输。
    4. 完成通信后,关闭 SocketServerSocket

    服务器端示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    import java.io.*;
    import java.net.*;

    public class Server {
    public static void main(String[] args) throws IOException {
    ServerSocket serverSocket = new ServerSocket(8080);
    System.out.println("Server is listening on port 8080");
    Socket socket = serverSocket.accept();

    InputStream input = socket.getInputStream();
    BufferedReader reader = new BufferedReader(new InputStreamReader(input));
    String message = reader.readLine();
    System.out.println("Received from client: " + message);

    socket.close();
    serverSocket.close();
    }
    }
  • 客户端

    1. 创建 Socket 对象并连接到服务器的 IP 地址和端口。
    2. 使用输入输出流与服务器进行数据传输。
    3. 通信完成后,关闭 Socket

    客户端示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import java.io.*;
    import java.net.*;

    public class Client {
    public static void main(String[] args) throws IOException {
    Socket socket = new Socket("localhost", 8080);

    OutputStream output = socket.getOutputStream();
    PrintWriter writer = new PrintWriter(output, true);
    writer.println("Hello, Server!");

    socket.close();
    }
    }

5. 描述如何使用 JDBC 编写程序

JDBC(Java Database Connectivity)用于连接和操作数据库。使用 JDBC 编写程序的基本步骤如下:

  1. 加载数据库驱动:首先需要加载对应数据库的 JDBC 驱动程序。例如,使用 MySQL 时可以加载 com.mysql.cj.jdbc.Driver

    1
    Class.forName("com.mysql.cj.jdbc.Driver");
  2. 建立数据库连接:使用 DriverManager 类的 getConnection() 方法,传入数据库的 URL、用户名和密码,建立数据库连接。

    1
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "password");
  3. 创建 SQL 语句:使用 Connection 对象的 createStatement() 方法创建 Statement 或使用 prepareStatement() 方法创建预编译的 SQL 语句。

    1
    Statement stmt = conn.createStatement();
  4. 执行 SQL 查询:通过 executeQuery()executeUpdate() 方法执行 SQL 查询或更新操作。

    1
    ResultSet rs = stmt.executeQuery("SELECT * FROM users");
  5. 处理结果集:遍历 ResultSet 对象,处理查询结果。

    1
    2
    3
    while (rs.next()) {
    System.out.println(rs.getString("name"));
    }
  6. 关闭连接:完成数据库操作后,关闭 ResultSetStatementConnection

    1
    2
    3
    rs.close();
    stmt.close();
    conn.close();

JDBC 示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import java.sql.*;

public class JdbcExample {
public static void main(String[] args) {
try {
// 加载驱动程序
Class.forName("com.mysql.cj.jdbc.Driver");

// 建立连接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "password");

// 创建语句
Statement stmt = conn.createStatement();

// 执行查询
ResultSet rs = stmt.executeQuery("SELECT * FROM users");

// 处理结果
while (rs.next()) {
System.out.println(rs.getString("name"));
}

// 关闭连接
rs.close();
stmt.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}