内部类、嵌套类和匿名类
本课属于 Coddy Java 学习旅程的“面向对象编程”单元。第 49 课,共 87 课。
Java 允许你在其他类中定义类。这些内部类可以将相关功能组合在一起,帮助整理代码,并且可以直接访问外部类的成员。
嵌套内部类定义为另一个类的成员。它可以访问外部类的所有字段和方法,包括私有字段和方法:
class Outer {
private String message = "Hello";
class Inner {
void display() {
System.out.println(message); // 可以访问私有字段
}
}
}
// 用法
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.display(); // 输出:Hello局部内部类定义在方法内部。它只能在该方法内使用,并且可以访问实际上为 final 的局部变量:
void process() {
String prefix = "Result: ";
class LocalHelper {
void print(int value) {
System.out.println(prefix + value);
}
}
new LocalHelper().print(42);
}匿名内部类是一个没有名称的类,在一个表达式中创建并实例化。它通常用于即时实现接口或扩展类:
Comparator<String> comp = new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.length() - b.length();
}
};当一个类只与另一个类有关时,内部类尤其有用,可以让代码更整洁、更封装。
挑战
简单我们来构建一个购物车系统,展示三种内部类。你将创建一个 ShoppingCart,使用嵌套内部类表示商品,使用局部内部类计算折扣,并使用匿名内部类格式化最终收据。
你需要将代码分成两个文件:
ShoppingCart.java:创建一个管理购物体验的外部类。你的 ShoppingCart 应有一个私有字段customerName(String)。在 ShoppingCart 内部,定义一个名为
Item的嵌套内部类,其中包含两个私有字段:name(String)和price(double)。为 Item 添加一个构造函数,用于初始化这两个字段;再添加一个getDetails()方法,返回:[name]: $[price]你的 ShoppingCart 需要一个接收顾客姓名的构造函数,以及一个名为
checkout()的方法,该方法接收一个 Item 和一个折扣百分比(double)。在checkout()内部:- 创建一个名为
DiscountCalculator的局部内部类,其中包含一个applyDiscount(double originalPrice)方法,返回应用折扣百分比后的价格。 - 使用这个局部类计算最终价格。
- 创建一个实现
Formatter接口的匿名内部类(你将定义此接口),用于格式化收据。匿名类应重写format()方法,并返回一个多行收据字符串。
checkout()方法应返回格式如下的收据字符串:--- Receipt --- Customer: [customerName] Item: [item details from getDetails()] Discount: [discount]% Final Price: $[calculated price]- 创建一个名为
Formatter.java:定义一个只有一个方法的简单接口:String format()。你的匿名内部类将在 checkout 方法中实现此接口。Main.java:让你的购物车运转起来!你会收到三个输入:顾客姓名(String)、商品名称(String)和商品价格(double)。折扣百分比固定为10.0。使用顾客姓名创建一个 ShoppingCart。然后使用外部类引用语法创建一个 Item:
cart.new Item(name, price)。使用该商品和折扣调用checkout(),并打印返回的收据。
你会依次收到三个输入:顾客姓名、商品名称和商品价格。
例如,如果输入是 Alice、Laptop 和 1000.0,那么打 10% 折扣后的最终价格将是 900.0。
请注意,每种内部类都有不同的用途:嵌套类将相关数据与外部类组合在一起,局部类封装仅在一个方法中需要的逻辑,而匿名类则可以快速实现一次接口!
亲手试试
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取输入
String customerName = scanner.nextLine();
String itemName = scanner.nextLine();
double itemPrice = scanner.nextDouble();
double discount = 10.0;
// TODO: 用客户姓名创建一个 ShoppingCart
// TODO: 使用 cart.new Item(itemName, itemPrice) 创建一个 Item
// TODO: 将商品和折扣传给 checkout(),然后打印结果
}
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Java 在线编译器