Java面向对象程序设计试题
考试时间: 120分钟 总分: 100分
单项选择题 (每题2分,共20分)
-
在Java中,以下哪个关键字用于创建一个对象? A.
typeB.classC.newD.import -
下列关于
this关键字的描述,哪一个是错误的? A.this可以用来引用当前类的实例方法。 B.this可以用来调用当前类的构造方法。 C.this代表对当前对象的引用。 D.this可以在静态方法中使用。 -
以下哪个修饰符修饰的成员变量,可以被任何其他类的任何方法访问? A.
privateB.protectedC.publicD.default(即不加任何修饰符) -
关于抽象类和接口,以下说法正确的是? A. 一个类可以实现多个抽象类,但只能实现一个接口。 B. 抽象类中可以有构造方法,接口中不能有。 C. 接口中的方法默认是
public abstract的,而抽象类中的方法可以是任何修饰符。 D. 抽象类和接口都不能包含实例字段(成员变量)。 -
在Java中,
String类被声明为final,这意味着什么? A.String类不能被继承。 B.String可以被修改。 C.String类的所有方法都是静态的。 D.String类只能创建一个实例。 -
下列哪个选项是Java中合法的方法重载?
class Animal { void makeSound() { ... } // 以下哪个是makeSound的重载? }A.
int makeSound() { ... }B.void makeSound(String name) { ... }C.static void makeSound() { ... }D.void makeSound() throws Exception { ... } -
关于Java的垃圾回收机制,以下描述最准确的是? A. 程序员必须手动调用
System.gc()来回收内存。 B. 垃圾回收器会立即回收所有不再被引用的对象。 C. 垃圾回收是Java自动管理的,程序员无法精确控制其执行时机。 D. 一个对象在没有任何引用指向它时,就会被垃圾回收器立即回收。 -
以下代码的输出是什么?
public class Test { public static void main(String[] args) { String a = "hello"; String b = new String("hello"); System.out.println(a == b); System.out.println(a.equals(b)); } }A.
true,trueB.false,trueC.true,falseD.false,false -
在Java中,
final关键字不能用来修饰以下哪个元素? A. 类 B. 方法 C. 成员变量 D. 接口 -
下列关于
static关键字的描述,错误的是? A.static方法不能访问非static的成员变量。 B.static方法属于类,而不是类的某个实例。 C.static代码块在类被加载时执行,且只执行一次。 D.static内部类可以访问其外部类的所有成员(包括非静态成员)。
填空题 (每空2分,共20分)
- 面向对象编程的三大基本特征是:__、__、__。
- 如果一个类没有定义构造方法,Java编译器会为其提供一个默认的__构造方法。
- 在Java中,所有类的根父类是__。
super关键字有两个主要用途:一是调用父类的__,二是访问父类的__。- 当一个类实现了
Serializable接口时,表示该类的对象可以被__。 - 方法重写要求子类方法的访问权限不能比父类方法的__更严格。
- 在Java中,使用
__________关键字可以防止一个类被继承。 - 一个类如果声明为
abstract,则它不能被__。
简答题 (每题5分,共20分)
- 简述运算符和
equals()方法在Java中的区别。 - 什么是多态?请用一句话概括,并说明实现多态的三个必要条件。
- 什么是内部类?内部类主要有哪几种?
- 请解释
String,StringBuilder,StringBuffer三者之间的区别。
代码分析题 (共20分)
阅读以下代码,回答问题:
class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + " is eating.");
}
public void sleep() {
System.out.println(name + " is sleeping.");
}
}
class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void eat() {
System.out.println(getName() + " the dog is eating bones.");
}
public void bark() {
System.out.println(getName() + " says: Woof!");
}
}
class Cat extends Animal {
public Cat(String name) {
super(name);
}
@Override
public void eat() {
System.out.println(getName() + " the cat is eating fish.");
}
}
public class TestPolymorphism {
public static void main(String[] args) {
Animal a1 = new Dog("Buddy");
Animal a2 = new Cat("Whiskers");
// 问题1: 调用a1.eat()和a1.bark(),输出结果是什么?为什么? (8分)
// 问题2: 调用a2.eat(),输出结果是什么?这体现了什么特性? (6分)
// 问题3: 如果想调用a1.bark(),应该如何修改代码? (6分)
}
}
编程题 (共20分)
** 设计一个简单的Shape(形状)类体系。
- 定义一个抽象类
Shape,它包含一个抽象方法calculateArea(),用于计算面积。 - 定义
Shape的子类Circle(圆形)和Rectangle(矩形)。Circle类包含一个私有成员变量radius(半径),并提供一个构造方法来初始化半径,实现calculateArea()方法,计算公式为π * radius * radius。Rectangle类包含两个私有成员变量width(宽)和height(高),并提供一个构造方法来初始化它们,实现calculateArea()方法,计算公式为width * height。
- 在
main方法中,创建一个Circle对象和一个Rectangle对象,将它们都存储在Shape类型的数组中,然后遍历该数组,调用每个对象的calculateArea()方法并打印结果。
要求:
- 代码结构清晰,命名规范。
- 必须使用抽象类和继承。
- 计算圆周率时,请使用
Math.PI。
参考答案与解析
单项选择题
-
C.
new- 解析:
new是Java中用于在堆内存上创建对象实例的关键字。class是定义类的关键字,type不是Java关键字,import用于导入包。
- 解析:
-
D.
this可以在静态方法中使用。- 解析:
this指代当前对象实例,而静态方法属于类,不属于任何实例,因此在静态方法中不能使用this。
- 解析:
-
C.
public- 解析:
public修饰符的成员具有最大的访问权限,可以被任何地方的代码访问。
- 解析:
-
B. 抽象类中可以有构造方法,接口中不能有。
- 解析: 抽象类也是类,可以有构造方法(用于子类初始化父类部分),接口中不能有构造方法,因为它不能被实例化,A选项错误,一个类可以实现多个接口,但只能继承一个抽象类(单继承),C选项错误,接口中的方法默认是
public abstract,但Java 9+后可以有private方法,D选项错误,接口可以包含public static final的常量。
- 解析: 抽象类也是类,可以有构造方法(用于子类初始化父类部分),接口中不能有构造方法,因为它不能被实例化,A选项错误,一个类可以实现多个接口,但只能继承一个抽象类(单继承),C选项错误,接口中的方法默认是
-
A.
String类不能被继承。- 解析:
final修饰类表示该类不能被继承。String类是不可变的,这也是其设计的一部分。
- 解析:
-
B.
void makeSound(String name) { ... }- 解析: 方法重载要求方法名相同,但参数列表不同(参数个数、类型或顺序不同),A选项返回类型不同,不是重载的判断依据,C选项
static关键字不同,不是重载,D选项异常列表不同,也不是重载。
- 解析: 方法重载要求方法名相同,但参数列表不同(参数个数、类型或顺序不同),A选项返回类型不同,不是重载的判断依据,C选项
-
C. 垃圾回收是Java自动管理的,程序员无法精确控制其执行时机。
- 解析: 垃圾回收是自动的,
System.gc()只是建议JVM回收,但不保证立即执行,回收时机是不确定的。
- 解析: 垃圾回收是自动的,
-
B.
false,true- 解析: 比较的是两个对象在内存中的地址。
a指向字符串常量池中的"hello",b通过new在堆上创建了一个新的String对象,所以地址不同,a == b为false。equals()方法比较的是字符串的内容,两者内容都是"hello",所以a.equals(b)为true。
- 解析: 比较的是两个对象在内存中的地址。
-
D. 接口
- 解析:
final可以修饰类(不能被继承)、方法(不能被重写)、变量(常量),接口不能被final修饰,因为接口的本质是定义规范,可以被实现。
- 解析:
-
D.
static内部类可以访问其外部类的所有成员(包括非静态成员)。- 解析:
static内部类也叫静态内部类,它只持有外部类的引用,不能直接访问外部类的非静态成员,必须通过外部类的对象实例来访问,而非静态内部类(成员内部类)可以访问外部类的所有成员。
- 解析:
填空题
- 封装、继承、多态
- 解析: 面向对象的三大基石。
- 无参
- 解析: 默认构造方法没有参数。
- Object
- 解析: Java中所有类都直接或间接继承自
Object类。
- 解析: Java中所有类都直接或间接继承自
- 构造方法、成员变量
- 解析:
super()用于调用父类构造方法,super.成员变量用于访问父类的成员变量(当子类与父类成员变量同名时)。
- 解析:
- 序列化
- 解析:
Serializable是一个标记接口,实现了它,对象就可以被转换为字节流,以便存储或传输。
- 解析:
- 访问权限
- 解析: 这是重写规则之一,子类方法的访问权限必须大于或等于父类方法的访问权限(父类是
public,子类不能是protected)。
- 解析: 这是重写规则之一,子类方法的访问权限必须大于或等于父类方法的访问权限(父类是
- final
- 解析: 被
final修饰的类不能被继承。
- 解析: 被
- 实例化
- 解析: 抽象类不完整,不能直接创建对象(实例化)。
简答题
-
和
equals()的区别:- 是一个运算符,对于基本数据类型,它比较的是值是否相等;对于引用数据类型(如对象),它比较的是两个引用变量是否指向堆内存中的同一个对象(即地址是否相同)。
equals():是一个方法。Object类中的equals()方法与作用相同,但很多类(如String,Integer等)都重写了equals()方法,用于比较对象的内容(值)是否相等,而不是地址。
-
多态:
- 概括: 多态指同一个接口,使用不同的实例而执行不同操作。
- 三个必要条件:
- 继承:必须有类之间的继承关系。
- 重写:子类必须重写父类的方法。
- 向上转型:父类引用指向子类对象。
-
内部类:
- 定义: 内部类是定义在另一个类内部的类。
- 主要种类:
- 成员内部类:定义在外部类的成员位置。
- 静态内部类:使用
static修饰的成员内部类。 - 局部内部类:定义在外部类的方法或作用域块内。
- 匿名内部类:没有名字的局部内部类。
-
String,StringBuilder,StringBuffer的区别:String:字符串是不可变的,每次修改String对象(如连接)都会创建一个新的String对象,效率较低,但线程安全,因为内容不会被改变。StringBuilder:字符串是可变的,提供了修改字符串的方法(如append,insert),性能高,但非线程安全。StringBuffer:字符串是可变的,与StringBuilder功能几乎完全相同,但它是线程安全的(方法大多被synchronized修饰),因此在多线程环境下更安全,但性能稍差。
代码分析题
-
问题1:
- 输出结果:
Buddy the dog is eating bones. 编译错误。 - 原因:
a1是Animal类型的引用,它只能访问Animal类中定义的方法或被子类重写的方法。eat()方法被Dog类重写了,所以调用的是Dog类的eat()方法,而bark()方法是Dog类特有的,Animal类中没有定义,因此编译器会报错,提示找不到bark()方法。
- 输出结果:
-
问题2:
- 输出结果:
Whiskers the cat is eating fish. - 体现的特性: 多态。
a2是Animal类型的引用,但它指向一个Cat对象,当调用a2.eat()时,JVM在运行时会根据a2实际指向的对象类型(Cat)来调用Cat类中重写的eat()方法,这就是运行时多态。
- 输出结果:
-
问题3:
- 修改方法: 将
a1的引用类型强制转换为Dog类型。// 修改前 // a1.bark(); // 编译错误
// 修改后 if (a1 instanceof Dog) { Dog dog = (Dog) a1; dog.bark(); // 现在可以成功调用 }
* **解析:** 使用`instanceof`操作符进行类型检查,确保`a1`确实是`Dog`类型的实例,然后进行强制类型转换,将其转换为`Dog`引用,这样就能调用`Dog`类特有的`bark()`方法了。 - 修改方法: 将
编程题
// 1. 定义抽象类 Shape
abstract class Shape {
// 抽象方法,没有方法体
public abstract double calculateArea();
}
// 2. 定义子类 Circle
class Circle extends Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double calculateArea() {
// 使用 Math.PI 计算圆的面积
return Math.PI * radius * radius;
}
}
// 2. 定义子类 Rectangle
class Rectangle extends Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double calculateArea() {
return width * height;
}
}
// 3. 主类
public class ShapeTest {
public static void main(String[] args) {
// 创建 Shape 类型的数组,并存放子类对象
Shape[] shapes = new Shape[2];
shapes[0] = new Circle(5.0);
shapes[1] = new Rectangle(4.0, 6.0);
// 遍历数组,调用 calculateArea() 方法并打印结果
for (Shape shape : shapes) {
// 这里体现了多态,根据实际对象类型调用相应的 calculateArea() 方法
System.out.println("The area is: " + shape.calculateArea());
}
}
}
输出结果:
The area is: 78.53981633974483
The area is: 24.0 