杰瑞科技汇

Java面向对象试题有哪些核心考点?

面向对象程序设计 Java 试题

考试时间: 120分钟 总分: 100分

Java面向对象试题有哪些核心考点?-图1
(图片来源网络,侵删)

第一部分:选择题 (共20分,每题2分)

说明: 请在每道题的四个选项中选择一个最合适的答案。

  1. 下列关于面向对象编程的描述中,不正确的是? A. 封装是将对象的属性和操作捆绑在一起,并对外部隐藏实现细节。 B. 继承允许一个类获取另一个类的属性和方法,是实现代码复用的重要手段。 C. 多态是指同一个接口,使用不同的实例而执行不同操作的能力。 O. D. 面向对象编程的核心思想是“过程化”,即关注解决问题的步骤。

  2. 在Java中,以下哪个关键字用于创建一个类的实例(对象)? A. type B. class C. new D. instanceof

  3. 下列哪个是Java中合法的标识符? A. 123variable B. $_variable C. class D. variable-name

    Java面向对象试题有哪些核心考点?-图2
    (图片来源网络,侵删)
  4. 关于final关键字,以下说法正确的是? A. final类可以被继承。 B. final方法可以被重写。 C. C. final变量一旦被赋值,就不能再被修改。 D. final修饰的局部变量必须在声明时就初始化。

  5. 在Java中,String类是? A. 基本数据类型 B. 引用数据类型,且是不可变的 C. 引用数据类型,是可变的 D. 一个接口

  6. 以下哪个选项是ArrayListLinkedList最主要的区别? A. ArrayList是线程安全的,LinkedList不是。 B. ArrayList存储的是对象,LinkedList存储的是基本数据类型。 C. C. ArrayList基于动态数组,查找快;LinkedList基于链表,增删快。 D. ArrayList有容量限制,LinkedList没有。

  7. 以下代码的输出是什么?

    public class Test {
        public static void main(String[] args) {
            int a = 10;
            int b = 20;
            System.out.println(a + b + " is the sum.");
            System.out.println("The sum is " + a + b);
        }
    }

    A.

    30 is the sum.
    The sum is 30

    B.

    30 is the sum.
    The sum is 1020

    C.

    10+20 is the sum.
    The sum is 30

    D. 编译错误

  8. 以下关于抽象类和接口的说法,错误的是? A. 一个类可以实现多个接口,但只能继承一个抽象类。 B. 接口中的方法默认是public abstract的。 C. C. 抽象类中可以有构造方法,而接口中不能有。 D. Java 8开始,接口中可以包含默认方法和静态方法。

  9. 以下哪个方法可以被重写? A. private void methodA() {} B. static void methodB() {} C. final void methodC() {} D. D. protected void methodD() {}

  10. 在Java中,super关键字的作用不包括? A. 调用父类的构造方法 B. 调用父类的成员变量 C. 调用父类的成员方法 D. D. 创建父类的对象


第二部分:编程题 (共50分)

说明: 请根据题目要求,编写完整的Java代码。

(15分) 设计一个简单的银行账户系统

要求:

  1. 创建一个BankAccount类,包含以下属性:
    • accountNumber (账户号,String类型)
    • ownerName (户主姓名,String类型)
    • balance (余额,double类型)
  2. BankAccount类提供构造方法,用于初始化账户号和户主姓名,初始余额为0。
  3. 实现以下方法:
    • deposit(double amount): 存款方法,如果存款金额大于0,则增加余额。
    • withdraw(double amount): 取款方法,如果取款金额大于0且小于等于余额,则减少余额;否则打印提示信息。
    • getBalance(): 获取当前余额。
    • displayAccountInfo(): 打印账户信息(账户号、户主、余额)。
  4. main方法中,创建一个BankAccount对象,并进行存款和取款操作,最后显示账户信息。
// 在此编写你的代码

(20分) 实现一个员工管理系统

要求:

  1. 创建一个抽象类Employee,包含:
    • 属性:name (姓名), id (工号)
    • 构造方法:Employee(String name, String id)
    • 抽象方法:calculateSalary() (计算工资)
    • 普通方法:displayInfo() (显示员工基本信息)
  2. 创建两个子类SalariedEmployee (月薪员工) 和 HourlyEmployee (时薪员工) 继承自Employee
    • SalariedEmployee增加属性monthlySalary (月薪),并重写calculateSalary()方法返回monthlySalary
    • HourlyEmployee增加属性hourlyRate (时薪) 和 hoursWorked (工作小时数),并重写calculateSalary()方法返回hourlyRate * hoursWorked
  3. 创建一个EmployeeManagementSystem类,包含一个Employee类型的数组,用于存储员工对象。
  4. main方法中,创建几个SalariedEmployeeHourlyEmployee对象,添加到系统中,并遍历数组,打印每个员工的信息和工资。
// 在此编写你的代码

(15分) 使用集合和异常处理

要求:

  1. 创建一个Product类,包含productId (产品ID) 和 productName (产品名称) 属性,以及相应的构造方法和toString()方法。
  2. 编写一个ProductManager类,使用HashMap<String, Product>来管理产品,其中键是productId,值是Product对象。
  3. ProductManager类提供以下方法:
    • addProduct(Product product): 添加产品,如果产品ID已存在,则抛出一个自定义异常DuplicateProductException
    • getProduct(String productId): 根据ID获取产品,如果产品不存在,则抛出一个NullPointerException或自定义异常。
    • listAllProducts(): 遍历并打印所有产品信息。
  4. main方法中,测试ProductManager的功能,包括正常添加、重复添加异常、获取不存在的产品异常等情况,并使用try-catch块来处理异常。
// 在此编写你的代码

第三部分:简答题 (共30分)

说明: 请用简洁明了的语言回答下列问题。

  1. (10分) 简述Java中和equals()方法的区别。
  2. (10分) 什么是多态?请结合Java代码(例如一个父类引用指向子类对象)举例说明它的好处。
  3. (10分) 请解释String, StringBuilder, 和 StringBuffer三者之间的主要区别。


参考答案与解析


第一部分:选择题

  1. D,面向对象编程的核心思想是“对象化”,将数据和处理数据的方法封装在一起,以对象为中心,而“过程化”是面向过程编程的核心思想。
  2. Cnew是Java中用于在堆内存上创建对象实例的关键字。
  3. B,标识符必须以字母、下划线_或美元符开头,不能是数字。class是关键字,不能用作标识符。
  4. Cfinal变量(常量)一旦被初始化,就不能再被修改。final类不能被继承,final方法不能被重写。final局部变量可以在声明时或在使用前初始化。
  5. BString是一个位于java.lang包中的类,是引用数据类型,它的所有对象都是不可变的,一旦创建,内容不能改变。
  6. C,这是两者最核心的区别。ArrayList基于数组,索引查找(get)时间复杂度为O(1);LinkedList基于双向链表,增删节点(add, remove)时间复杂度为O(1),但查找需要遍历,为O(n)。
  7. B,Java中,字符串连接是从左到右进行的,第一句a + b + "...",先计算a+b得到30,再与字符串连接,第二句"..." + a + b,先进行字符串连接,得到"The sum is 10",然后再与b连接,最终得到"The sum is 1020"。
  8. C,抽象类也是类,可以有构造方法,用于在创建子类实例时初始化父类的部分属性,接口默认没有构造方法(虽然可以有静态初始化块),接口中也不能有实例字段。
  9. D,可以被重写的方法不能是private, static, 或 final的。protectedpublic(在同一个包或不同包的子类中)的方法可以被重写。
  10. Dsuper用于在子类中引用父类的成员(变量、方法)或调用父类的构造方法,它本身不能用来创建对象。

第二部分:编程题

设计一个简单的银行账户系统

public class BankAccount {
    private String accountNumber;
    private String ownerName;
    private double balance;
    public BankAccount(String accountNumber, String ownerName) {
        this.accountNumber = accountNumber;
        this.ownerName = ownerName;
        this.balance = 0.0;
    }
    public void deposit(double amount) {
        if (amount > 0) {
            this.balance += amount;
            System.out.println("存款成功: " + amount);
        } else {
            System.out.println("存款金额必须大于0。");
        }
    }
    public void withdraw(double amount) {
        if (amount > 0 && amount <= this.balance) {
            this.balance -= amount;
            System.out.println("取款成功: " + amount);
        } else if (amount > this.balance) {
            System.out.println("余额不足,取款失败。");
        } else {
            System.out.println("取款金额必须大于0。");
        }
    }
    public double getBalance() {
        return this.balance;
    }
    public void displayAccountInfo() {
        System.out.println("===== 账户信息 =====");
        System.out.println("账户号: " + this.accountNumber);
        System.out.println("户主姓名: " + this.ownerName);
        System.out.println("当前余额: " + this.balance);
        System.out.println("===================");
    }
    public static void main(String[] args) {
        BankAccount myAccount = new BankAccount("123456789", "张三");
        myAccount.displayAccountInfo();
        myAccount.deposit(1000);
        System.out.println("当前余额: " + myAccount.getBalance());
        myAccount.withdraw(500);
        System.out.println("当前余额: " + myAccount.getBalance());
        myAccount.withdraw(600); // 测试余额不足的情况
        myAccount.displayAccountInfo();
    }
}

实现一个员工管理系统

// 抽象类 Employee
abstract class Employee {
    protected String name;
    protected String id;
    public Employee(String name, String id) {
        this.name = name;
        this.id = id;
    }
    public abstract double calculateSalary();
    public void displayInfo() {
        System.out.println("员工ID: " + id + ", 姓名: " + name);
    }
}
// 子类 SalariedEmployee
class SalariedEmployee extends Employee {
    private double monthlySalary;
    public SalariedEmployee(String name, String id, double monthlySalary) {
        super(name, id);
        this.monthlySalary = monthlySalary;
    }
    @Override
    public double calculateSalary() {
        return monthlySalary;
    }
    @Override
    public void displayInfo() {
        super.displayInfo();
        System.out.println("类型: 月薪员工, 月薪: " + monthlySalary);
    }
}
// 子类 HourlyEmployee
class HourlyEmployee extends Employee {
    private double hourlyRate;
    private double hoursWorked;
    public HourlyEmployee(String name, String id, double hourlyRate, double hoursWorked) {
        super(name, id);
        this.hourlyRate = hourlyRate;
        this.hoursWorked = hoursWorked;
    }
    @Override
    public double calculateSalary() {
        return hourlyRate * hoursWorked;
    }
    @Override
    public void displayInfo() {
        super.displayInfo();
        System.out.println("类型: 时薪员工, 时薪: " + hourlyRate + ", 工作时长: " + hoursWorked);
    }
}
// 管理系统类
public class EmployeeManagementSystem {
    public static void main(String[] args) {
        Employee[] employees = new Employee[3];
        employees[0] = new SalariedEmployee("李四", "E001", 15000);
        employees[1] = new HourlyEmployee("王五", "E002", 100, 160);
        employees[2] = new SalariedEmployee("赵六", "E003", 20000);
        System.out.println("--- 员工工资单 ---");
        for (Employee emp : employees) {
            emp.displayInfo();
            System.out.println("应发工资: " + emp.calculateSalary());
            System.out.println("-----------------");
        }
    }
}

使用集合和异常处理

// 自定义异常
class DuplicateProductException extends Exception {
    public DuplicateProductException(String message) {
        super(message);
    }
}
// Product 类
class Product {
    private String productId;
    private String productName;
    public Product(String productId, String productName) {
        this.productId = productId;
        this.productName = productName;
    }
    @Override
    public String toString() {
        return "ID: " + productId + ", 名称: " + productName;
    }
}
// ProductManager 类
import java.util.HashMap;
class ProductManager {
    private HashMap<String, Product> productMap;
    public ProductManager() {
        this.productMap = new HashMap<>();
    }
    public void addProduct(Product product) throws DuplicateProductException {
        if (productMap.containsKey(product.getProductId())) {
            throw new DuplicateProductException("产品ID " + product.getProductId() + " 已存在!");
        }
        productMap.put(product.getProductId(), product);
        System.out.println("产品添加成功: " + product);
    }
    public Product getProduct(String productId) throws NullPointerException {
        Product product = productMap.get(productId);
        if (product == null) {
            throw new NullPointerException("产品ID " + productId + " 不存在!");
        }
        return product;
    }
    public void listAllProducts() {
        System.out.println("--- 所有产品列表 ---");
        if (productMap.isEmpty()) {
            System.out.println("暂无产品。");
        } else {
            for (Product p : productMap.values()) {
                System.out.println(p);
            }
        }
        System.out.println("--------------------");
    }
    // 假设Product类有getter
    public String getProductId() { return productId; } // 需要添加到Product类中
    public String getProductName() { return productName; } // 需要添加到Product类中
}
// 测试类
public class TestProductManager {
    public static void main(String[] args) {
        ProductManager manager = new ProductManager();
        try {
            manager.addProduct(new Product("P001", "笔记本电脑"));
            manager.addProduct(new Product("P002", "无线鼠标"));
            // 尝试添加重复ID的产品
            manager.addProduct(new Product("P001", "键盘")); // 会抛出异常
        } catch (DuplicateProductException e) {
            System.out.println("错误: " + e.getMessage());
        }
        manager.listAllProducts();
        try {
            Product p = manager.getProduct("P002");
            System.out.println("找到产品: " + p);
            // 尝试获取不存在的产品
            Product pNotFound = manager.getProduct("P999"); // 会抛出异常
        } catch (NullPointerException e) {
            System.out.println("错误: " + e.getMessage());
        }
    }
}

注意:为了让ProductManagergetProduct方法能正确编译,需要在Product类中添加getProductId()getProductName()方法。


第三部分:简答题

  1. equals() 的区别

    • :
      • 如果比较的是基本数据类型(如 int, double),它比较的是两个值是否相等。
      • 如果比较的是引用数据类型(如 Object, String),它比较的是两个引用变量是否指向内存中的同一个对象(即地址是否相同)。
    • equals():
      • equals()Object类中的一个方法,用于比较两个对象在“逻辑上”是否相等。
      • Object类中的equals()方法默认实现也是使用来比较,即比较地址。
      • 许多类(如String, Integer, ArrayList等)都重写了equals()方法,以实现更有意义的逻辑比较。String类的equals()方法比较的是字符串内容是否相同。
    • 比较的是内存地址(引用)或值,而 equals() 比较的是对象的内容(逻辑相等),对于自定义类,如果不重写equals(),其行为和一样。
  2. 什么是多态?举例说明好处。

    • 定义: 多态是同一个行为具有多个不同表现形式或形态的能力,在Java中,多态通常指“一个父类类型的引用,可以指向其任何一个子类的对象”,并且通过这个引用调用方法时,会执行子类重写后的版本。

    • 代码示例:

      class Animal {
          public void makeSound() {
              System.out.println("动物发出声音");
          }
      }
      class Dog extends Animal {
          @Override
          public void makeSound() {
              System.out.println("汪汪汪!");
          }
      }
      class Cat extends Animal {
          @Override
          public void makeSound() {
              System.out.println("喵喵喵!");
          }
      }
      public class TestPolymorphism {
          public static void main(String[] args) {
              Animal myDog = new Dog(); // 父类引用指向子类对象
              Animal myCat = new Cat();
              myDog.makeSound(); // 输出: 汪汪汪!
              myCat.makeSound(); // 输出: 喵喵喵!
          }
      }
    • 好处:

      1. 提高代码的可扩展性和灵活性: 当需要增加新的子类(如Bird)时,不需要修改调用makeSound()方法的代码,只要Bird也继承Animal并重写makeSound()即可。
      2. 提高代码的通用性: 可以编写一个方法,它接收父类类型的参数,这样就可以接受任何子类的对象,大大减少了代码的重复。
        public void letAnimalMakeSound(Animal animal) {
            animal.makeSound();
        }
        letAnimalMakeSound(new Dog());
        letAnimalMakeSound(new Cat());
  3. String, StringBuilder, StringBuffer 的区别

    • String:
      • 不可变性: String对象一旦创建,其内容就不能被修改,任何修改String的操作(如concat, replace)都会生成一个新的String对象。
      • 线程安全: 因为不可变,所以天生是线程安全的。
      • 适用场景: 适用于少量字符串操作,或作为常量使用,频繁修改字符串会造成性能问题和内存浪费。
    • StringBuilder:
      • 可变性: StringBuilder可以被修改,它是一个可变的字符序列。
      • 线程安全: 非线程安全
      • 性能: 由于没有线程安全方面的开销,它的性能通常比StringBuffer要好,尤其是在单线程环境下。
      • 适用场景: 在单线程环境下进行大量的字符串拼接、修改操作。
    • StringBuffer:
      • 可变性: StringBuffer也是可变的。
      • 线程安全: 线程安全,它的大部分方法都使用了synchronized关键字进行同步。
      • 性能: 因为有线程安全的开销,所以性能比StringBuilder稍差。
      • 适用场景: 在多线程环境下,如果需要共享和修改字符串内容。
    • | 特性 | String | StringBuilder | StringBuffer | | :--- | :--- | :--- | :--- | | 可变性 | 不可变 | 可变 | 可变 | | 线程安全 | 安全 | 不安全 | 安全 | | 性能 | (修改时差) | 高 | 较低 | | 适用场景 | 少量操作,常量 | 单线程,大量修改 | 多线程,大量修改 |
分享:
扫描分享到社交APP
上一篇
下一篇