开启你的编程学习之旅

云课堂提供高质量的编程课程,从入门到精通,助你成为技术大牛

立即开始学习

Java 编程入门

作者: 赵老师 更新: 2024-03-18 阅读: 51234 难度: 初级
学习工具

4. Java 面向对象高级特性

Java 面向对象编程提供了继承、抽象类、接口、多态、内部类和异常处理等高级特性,这些特性使得代码更加灵活、可扩展和可维护。

继承 (Inheritance)

继承是面向对象编程的基石,允许子类继承父类的属性和方法:

继承示例
// 父类 class Animal { protected String name; protected int age; public Animal(String name, int age) { this.name = name; this.age = age; } public void eat() { System.out.println(name + "正在吃东西..."); } public void sleep() { System.out.println(name + "正在睡觉..."); } // getter 和 setter 方法 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } // 子类继承父类 class Dog extends Animal { private String breed; // 品种 public Dog(String name, int age, String breed) { super(name, age); // 调用父类构造方法 this.breed = breed; } // 子类特有的方法 public void bark() { System.out.println(name + "汪汪叫..."); } // 方法重写 (Override) @Override public void eat() { System.out.println(name + "正在吃狗粮..."); } // 子类特有的getter方法 public String getBreed() { return breed; } public void setBreed(String breed) { this.breed = breed; } } // 另一个子类 class Cat extends Animal { private String color; public Cat(String name, int age, String color) { super(name, age); this.color = color; } public void meow() { System.out.println(name + "喵喵叫..."); } @Override public void eat() { System.out.println(name + "正在吃猫粮..."); } public String getColor() { return color; } public void setColor(String color) { this.color = color; } } // 测试类 public class InheritanceDemo { public static void main(String[] args) { Dog dog = new Dog("小黑", 3, "金毛"); Cat cat = new Cat("小花", 2, "白色"); // 调用继承的方法 dog.eat(); // 输出: 小黑正在吃狗粮... dog.sleep(); // 输出: 小黑正在睡觉... dog.bark(); // 输出: 小黑汪汪叫... cat.eat(); // 输出: 小花正在吃猫粮... cat.sleep(); // 输出: 小花正在睡觉... cat.meow(); // 输出: 小花喵喵叫... // 访问继承的属性 System.out.println("狗的名字: " + dog.getName()); System.out.println("狗的品种: " + dog.getBreed()); System.out.println("猫的颜色: " + cat.getColor()); } }

抽象类 (Abstract Class)

抽象类不能实例化,用于定义子类必须实现的方法:

抽象类示例
// 抽象类 abstract class Shape { protected String color; public Shape(String color) { this.color = color; } // 抽象方法 - 子类必须实现 public abstract double calculateArea(); public abstract double calculatePerimeter(); // 具体方法 - 子类可以继承使用 public void displayInfo() { System.out.println("形状颜色: " + color); System.out.println("面积: " + calculateArea()); System.out.println("周长: " + calculatePerimeter()); } // getter 和 setter public String getColor() { return color; } public void setColor(String color) { this.color = color; } } // 具体子类 - 圆形 class Circle extends Shape { private double radius; public Circle(String color, double radius) { super(color); this.radius = radius; } @Override public double calculateArea() { return Math.PI * radius * radius; } @Override public double calculatePerimeter() { return 2 * Math.PI * radius; } public double getRadius() { return radius; } public void setRadius(double radius) { this.radius = radius; } } // 具体子类 - 矩形 class Rectangle extends Shape { private double width; private double height; public Rectangle(String color, double width, double height) { super(color); this.width = width; this.height = height; } @Override public double calculateArea() { return width * height; } @Override public double calculatePerimeter() { return 2 * (width + height); } public double getWidth() { return width; } public void setWidth(double width) { this.width = width; } public double getHeight() { return height; } public void setHeight(double height) { this.height = height; } } // 测试类 public class AbstractClassDemo { public static void main(String[] args) { // 不能实例化抽象类 // Shape shape = new Shape("红色"); // 编译错误 Circle circle = new Circle("蓝色", 5.0); Rectangle rectangle = new Rectangle("绿色", 4.0, 6.0); System.out.println("=== 圆形信息 ==="); circle.displayInfo(); System.out.println("\n=== 矩形信息 ==="); rectangle.displayInfo(); // 多态的使用 Shape[] shapes = {circle, rectangle}; System.out.println("\n=== 多态演示 ==="); for (Shape shape : shapes) { shape.displayInfo(); System.out.println("------------"); } } }

接口 (Interface)

接口定义了一组方法规范,类可以实现多个接口:

接口示例
// 接口定义 interface Flyable { // 接口中的常量 (默认 public static final) int MAX_SPEED = 1000; // 抽象方法 (Java 8之前) void fly(); // 默认方法 (Java 8+) default void takeOff() { System.out.println("准备起飞..."); } // 静态方法 (Java 8+) static void showMaxSpeed() { System.out.println("最大飞行速度: " + MAX_SPEED + " km/h"); } } interface Swimmable { void swim(); default void dive() { System.out.println("潜入水中..."); } } interface Runnable { void run(); default void walk() { System.out.println("正在行走..."); } } // 类实现多个接口 class Duck implements Flyable, Swimmable, Runnable { private String name; public Duck(String name) { this.name = name; } @Override public void fly() { System.out.println(name + "在低空飞行..."); } @Override public void swim() { System.out.println(name + "在水中游泳..."); } @Override public void run() { System.out.println(name + "在陆地上奔跑..."); } // 重写默认方法 @Override public void takeOff() { System.out.println(name + "从水面起飞..."); } public String getName() { return name; } public void setName(String name) { this.name = name; } } // 另一个实现类 class Airplane implements Flyable { private String model; public Airplane(String model) { this.model = model; } @Override public void fly() { System.out.println(model + "飞机在高空飞行..."); } public String getModel() { return model; } public void setModel(String model) { this.model = model; } } // 测试类 public class InterfaceDemo { public static void main(String[] args) { Duck duck = new Duck("唐老鸭"); Airplane airplane = new Airplane("波音747"); System.out.println("=== 鸭子行为 ==="); duck.takeOff(); duck.fly(); duck.swim(); duck.dive(); duck.run(); duck.walk(); System.out.println("\n=== 飞机行为 ==="); airplane.takeOff(); airplane.fly(); // 调用接口的静态方法 Flyable.showMaxSpeed(); // 多态的使用 Flyable[] flyables = {duck, airplane}; System.out.println("\n=== 多态飞行 ==="); for (Flyable flyable : flyables) { flyable.takeOff(); flyable.fly(); System.out.println("------------"); } } }

多态 (Polymorphism)

多态允许使用父类引用指向子类对象,提高代码的灵活性:

多态示例
// 父类 class Employee { protected String name; protected double baseSalary; public Employee(String name, double baseSalary) { this.name = name; this.baseSalary = baseSalary; } // 计算工资的方法 - 将在子类中被重写 public double calculateSalary() { return baseSalary; } public void displayInfo() { System.out.println("员工: " + name); System.out.println("基本工资: " + baseSalary); System.out.println("实发工资: " + calculateSalary()); } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getBaseSalary() { return baseSalary; } public void setBaseSalary(double baseSalary) { this.baseSalary = baseSalary; } } // 子类 - 经理 class Manager extends Employee { private double bonus; public Manager(String name, double baseSalary, double bonus) { super(name, baseSalary); this.bonus = bonus; } @Override public double calculateSalary() { return baseSalary + bonus; } @Override public void displayInfo() { super.displayInfo(); System.out.println("奖金: " + bonus); } public double getBonus() { return bonus; } public void setBonus(double bonus) { this.bonus = bonus; } } // 子类 - 程序员 class Programmer extends Employee { private int overtimeHours; private double overtimeRate; public Programmer(String name, double baseSalary, int overtimeHours, double overtimeRate) { super(name, baseSalary); this.overtimeHours = overtimeHours; this.overtimeRate = overtimeRate; } @Override public double calculateSalary() { return baseSalary + (overtimeHours * overtimeRate); } @Override public void displayInfo() { super.displayInfo(); System.out.println("加班时长: " + overtimeHours); System.out.println("加班费率: " + overtimeRate); } public int getOvertimeHours() { return overtimeHours; } public void setOvertimeHours(int overtimeHours) { this.overtimeHours = overtimeHours; } public double getOvertimeRate() { return overtimeRate; } public void setOvertimeRate(double overtimeRate) { this.overtimeRate = overtimeRate; } } // 测试类 public class PolymorphismDemo { public static void main(String[] args) { // 创建不同类型的员工 Employee emp1 = new Manager("张三", 8000, 3000); Employee emp2 = new Programmer("李四", 6000, 20, 50); Employee emp3 = new Employee("王五", 5000); // 多态数组 Employee[] employees = {emp1, emp2, emp3}; System.out.println("=== 员工工资信息 ==="); for (Employee emp : employees) { emp.displayInfo(); System.out.println("------------"); } // 计算总工资 double totalSalary = calculateTotalSalary(employees); System.out.println("总工资支出: " + totalSalary); // 类型检查和转换 System.out.println("\n=== 类型检查 ==="); for (Employee emp : employees) { if (emp instanceof Manager) { Manager manager = (Manager) emp; System.out.println(manager.getName() + " 是经理,奖金: " + manager.getBonus()); } else if (emp instanceof Programmer) { Programmer programmer = (Programmer) emp; System.out.println(programmer.getName() + " 是程序员,加班时长: " + programmer.getOvertimeHours()); } else { System.out.println(emp.getName() + " 是普通员工"); } } } // 多态方法 - 可以处理所有Employee子类 public static double calculateTotalSalary(Employee[] employees) { double total = 0; for (Employee emp : employees) { total += emp.calculateSalary(); } return total; } }

内部类 (Inner Class)

内部类是在另一个类的内部定义的类,可以访问外部类的成员:

内部类示例
// 外部类 class OuterClass { private String outerField = "外部类字段"; private static String staticOuterField = "静态外部类字段"; // 成员内部类 class MemberInnerClass { private String innerField = "成员内部类字段"; public void display() { System.out.println("访问外部类字段: " + outerField); System.out.println("访问静态外部类字段: " + staticOuterField); System.out.println("访问内部类字段: " + innerField); // 调用外部类方法 outerMethod(); } } // 静态内部类 static class StaticInnerClass { private String staticInnerField = "静态内部类字段"; public void display() { // 只能访问外部类的静态成员 System.out.println("访问静态外部类字段: " + staticOuterField); System.out.println("访问静态内部类字段: " + staticInnerField); // 不能访问非静态成员 // System.out.println(outerField); // 编译错误 } } // 方法内部类 (局部内部类) public void methodWithInnerClass() { final String localVariable = "局部变量"; class LocalInnerClass { public void display() { System.out.println("访问外部类字段: " + outerField); System.out.println("访问局部变量: " + localVariable); } } LocalInnerClass localInner = new LocalInnerClass(); localInner.display(); } // 匿名内部类 public void anonymousInnerClassDemo() { // 使用匿名内部类实现接口 Runnable runnable = new Runnable() { @Override public void run() { System.out.println("匿名内部类执行,访问外部字段: " + outerField); } }; new Thread(runnable).start(); } private void outerMethod() { System.out.println("外部类方法被调用"); } // 测试内部类的方法 public void testInnerClasses() { System.out.println("=== 成员内部类 ==="); MemberInnerClass memberInner = new MemberInnerClass(); memberInner.display(); System.out.println("\n=== 静态内部类 ==="); StaticInnerClass staticInner = new StaticInnerClass(); staticInner.display(); System.out.println("\n=== 方法内部类 ==="); methodWithInnerClass(); System.out.println("\n=== 匿名内部类 ==="); anonymousInnerClassDemo(); } } // 测试类 public class InnerClassDemo { public static void main(String[] args) { OuterClass outer = new OuterClass(); outer.testInnerClasses(); // 在其他类中创建内部类实例 System.out.println("\n=== 外部创建内部类 ==="); // 创建成员内部类实例 OuterClass.MemberInnerClass memberInner = outer.new MemberInnerClass(); memberInner.display(); // 创建静态内部类实例 OuterClass.StaticInnerClass staticInner = new OuterClass.StaticInnerClass(); staticInner.display(); } }

异常处理 (Exception Handling)

Java异常处理机制帮助程序优雅地处理运行时错误:

异常处理示例
import java.util.InputMismatchException; import java.util.Scanner; // 自定义异常类 class InsufficientFundsException extends Exception { private double amount; public InsufficientFundsException(double amount) { super("资金不足,还差: " + amount + " 元"); this.amount = amount; } public double getAmount() { return amount; } } class InvalidAmountException extends Exception { public InvalidAmountException(String message) { super(message); } } // 银行账户类 class BankAccount { private String accountNumber; private double balance; public BankAccount(String accountNumber, double initialBalance) { this.accountNumber = accountNumber; this.balance = initialBalance; } // 存款方法 public void deposit(double amount) throws InvalidAmountException { if (amount <= 0) { throw new InvalidAmountException("存款金额必须大于0"); } balance += amount; System.out.println("存款成功,当前余额: " + balance); } // 取款方法 public void withdraw(double amount) throws InsufficientFundsException, InvalidAmountException { if (amount <= 0) { throw new InvalidAmountException("取款金额必须大于0"); } if (amount > balance) { double needs = amount - balance; throw new InsufficientFundsException(needs); } balance -= amount; System.out.println("取款成功,当前余额: " + balance); } // 转账方法 public void transfer(BankAccount target, double amount) throws InsufficientFundsException, InvalidAmountException { this.withdraw(amount); // 可能抛出异常 target.deposit(amount); // 可能抛出异常 System.out.println("转账成功!"); } public String getAccountNumber() { return accountNumber; } public double getBalance() { return balance; } } // 测试类 public class ExceptionHandlingDemo { public static void main(String[] args) { BankAccount account1 = new BankAccount("123456", 1000); BankAccount account2 = new BankAccount("654321", 500); Scanner scanner = new Scanner(System.in); while (true) { System.out.println("\n=== 银行系统菜单 ==="); System.out.println("1. 存款"); System.out.println("2. 取款"); System.out.println("3. 转账"); System.out.println("4. 查询余额"); System.out.println("5. 退出"); System.out.print("请选择操作: "); try { int choice = scanner.nextInt(); switch (choice) { case 1: System.out.print("请输入存款金额: "); double depositAmount = scanner.nextDouble(); account1.deposit(depositAmount); break; case 2: System.out.print("请输入取款金额: "); double withdrawAmount = scanner.nextDouble(); account1.withdraw(withdrawAmount); break; case 3: System.out.print("请输入转账金额: "); double transferAmount = scanner.nextDouble(); account1.transfer(account2, transferAmount); break; case 4: System.out.println("账户 " + account1.getAccountNumber() + " 余额: " + account1.getBalance()); System.out.println("账户 " + account2.getAccountNumber() + " 余额: " + account2.getBalance()); break; case 5: System.out.println("感谢使用,再见!"); scanner.close(); return; default: System.out.println("无效的选择!"); } } catch (InputMismatchException e) { System.out.println("输入格式错误,请输入数字!"); scanner.nextLine(); // 清除错误输入 } catch (InsufficientFundsException e) { System.out.println("取款失败: " + e.getMessage()); System.out.println("还需要: " + e.getAmount() + " 元"); } catch (InvalidAmountException e) { System.out.println("操作失败: " + e.getMessage()); } catch (Exception e) { System.out.println("发生未知错误: " + e.getMessage()); e.printStackTrace(); } } } // 演示 finally 块的使用 public static void fileOperationDemo() { Scanner fileScanner = null; try { // 模拟文件操作 fileScanner = new Scanner(System.in); System.out.print("请输入文件名: "); String fileName = fileScanner.nextLine(); if (fileName.isEmpty()) { throw new IllegalArgumentException("文件名不能为空"); } System.out.println("正在处理文件: " + fileName); // 模拟文件处理逻辑 } catch (IllegalArgumentException e) { System.out.println("参数错误: " + e.getMessage()); } finally { // 无论是否发生异常,都会执行 finally 块 if (fileScanner != null) { fileScanner.close(); System.out.println("资源已释放"); } } } // 演示 try-with-resources (Java 7+) public static void tryWithResourcesDemo() { // 自动资源管理,不需要显式关闭 try (Scanner autoScanner = new Scanner(System.in)) { System.out.print("请输入数据: "); String data = autoScanner.nextLine(); System.out.println("你输入的是: " + data); } catch (Exception e) { System.out.println("发生错误: " + e.getMessage()); } // 资源会自动关闭 } }

关键概念总结

  • 继承:子类继承父类的属性和方法,实现代码复用
  • 抽象类:包含抽象方法的类,不能实例化,用于定义规范
  • 接口:定义方法规范,类可以实现多个接口,支持多重继承
  • 多态:同一操作作用于不同对象,可以有不同的解释和执行结果
  • 内部类:在类内部定义的类,可以更好地封装和组织代码
  • 异常处理:使用 try-catch-finally 处理程序运行时的错误

最佳实践

  1. 优先使用组合而不是继承
  2. 接口用于定义行为,抽象类用于代码复用
  3. 合理使用多态提高代码的灵活性
  4. 内部类应该只在外部类中使用时才定义
  5. 异常处理要具体,不要捕获所有异常
  6. 自定义异常要提供有意义的错误信息
  7. 使用 try-with-resources 自动管理资源

注意:这些面向对象的高级特性是Java编程的核心,熟练掌握它们对于编写高质量、可维护的Java代码至关重要。

提示: 这是一个重要的概念,需要特别注意理解和掌握。
注意: 这是一个常见的错误点,请避免犯同样的错误。