网站首页 > 精选教程 正文
内部类(Inner Class)和枚举(Enumeration, Enum)是Java编程语言中两种非常重要的特性,它们各自服务于不同的目的。
内部类(Inner Class)
内部类是定义在另一个类内部的类,内部类可以访问包含它的外部类的所有成员,包括私有变量和受保护的方法。外部类要访问内部类的成员,则需要通过内部类的对象来访问。内部类按照定义的位置和作用范围分为成员内部类、静态内部类、局部内部类和匿名内部类。
分类 | 描述 |
成员内部类 | 作为外部类的成员变量一样存在,可以访问外部类的所有成员。 |
静态内部类 | 增加了static关键字修饰的内部类,不需要对外部类的实例持有引用,可以直接通过外部类名来访问。 |
局部内部类 | 定义在方法、代码块内部的内部类,其作用域仅限于该方法或代码块。 |
匿名内部类 | 没有名字的内部类,通常用于简化代码,尤其在需要创建并实例化一个类,且仅使用一次的情况。 |
内部类的主要用途
用途 | 描述 |
隐藏实现细节 | 通过内部类,可以将某些实现细节隐藏在外部类中,使得外部类的接口更加简洁。 |
实现回调和事件处理 | 内部类常常用于实现回调函数或处理事件。 |
方便访问外部类的成员 | 内部类可以直接访问外部类的私有成员,这是外部类所不具备的特性。 |
内部类的使用提升了代码的封装性,使代码组织更清晰,同时也便于解决特定的设计问题,比如事件监听器等场景。
内部类示例
内部类的应用场景广泛,这里提供一个常见的内部类使用的例子,通过定义一个成员内部类模拟信用卡类及其对应的账单生成器。
public class CreditCard {
// 信用卡的基本信息
private String cardNumber;
private String holderName;
// 创建信用卡账单生成器的内部类
class BillGenerator {
// 账单相关的属性
private double balance;
private Date billingCycleEnd;
// 构造方法
public BillGenerator(double initialBalance, Date endDate) {
this.balance = initialBalance;
this.billingCycleEnd = endDate;
}
// 生成账单的方法
public void generateBill() {
// 这里假设有一个计算账单的过程
double totalAmountDue = calculateTotalAmountDue();
// 访问外部类的属性
System.out.println("信用卡号: " + CreditCard.this.cardNumber);
System.out.println("持卡人姓名: " + CreditCard.this.holderName);
System.out.println("账单周期结束日期: " + billingCycleEnd);
System.out.println("应付总额: " + totalAmountDue);
}
// 模拟计算账单金额的方法
private double calculateTotalAmountDue() {
return balance * 0.95; // 假设享受了5%的优惠
}
}
// 信用卡类的构造方法
public CreditCard(String number, String name) {
this.cardNumber = number;
this.holderName = name;
}
// 创建账单生成器实例的方法
public BillGenerator createBillGenerator(double initialBalance, Date endDate) {
return new BillGenerator(initialBalance, endDate);
}
// 测试用例
public static void main(String[] args) {
CreditCard cc = new CreditCard("1234-5678-9012-3456", "John Doe");
CreditCard.BillGenerator billGen = cc.createBillGenerator(1000.0, new Date());
billGen.generateBill();
}
}
在这个例子中,BillGenerator是CreditCard的成员内部类,负责生成信用卡账单。内部类可以直接访问外部类的成员变量,这使得内部类与外部类之间存在紧密的逻辑联系,提高了代码的封装性和可读性。外部类通过创建内部类的实例,可以为每张信用卡生成相应的账单。
内部类作用域和生命周期
局部内部类的作用域仅限于其所在的方法或代码块。当方法执行完毕或代码块结束时,局部内部类的实例也会被销毁。
枚举(Enumeration, Enum)
枚举是一种特殊的类,用来定义一组固定的、预设的常量集合,每个枚举值都是枚举类型的唯一实例。
- 在Java中,使用enum关键字定义枚举类型,每个枚举值都是枚举类型的一个实例,并且默认继承自java.lang.Enum类。
- 枚举类型可以有自己的构造函数、方法和变量,但构造函数默认是私有的,防止外部直接创建枚举实例,只能通过枚举列表中定义的枚举值来获得实例。
- 枚举类型天然具有线程安全性和序列化能力,且Java提供了内置的枚举方法,如values()返回所有枚举值的数组,valueOf()通过字符串名称获取枚举实例等。
枚举的主要用途
用途 | 描述 |
定义常量集 | 枚举类型用于定义一组相关的常量,例如一周的七天、一年的四个季节等。 |
类型安全 | 使用枚举类型比使用整数或字符串常量更加类型安全,因为枚举类型限制了可能的值。 |
增加可读性 | 枚举类型使代码更具可读性,因为它们提供了有意义的名称,而不是魔法数字或字符串。 |
枚举的主要用途是为了一组有限且预先知道的常量提供类型安全和更好的可读性,常用于状态机设计、日志级别、月份天数等固定选项的场景。
枚举的基本定义
枚举类型在Java中是一个特殊的类,它包含了一组固定的常量。使用enum定义枚举。
public enum Color {
RED, GREEN, BLUE, YELLOW
}
在这个例子中,Color是一个枚举类型,它包含了四个枚举常量:RED、GREEN、BLUE和YELLOW。
枚举常量的使用
可以像使用普通变量一样使用枚举常量。
Color favoriteColor = Color.RED;
if (favoriteColor == Color.RED) {
System.out.println("My favorite color is red.");
}
枚举构造方法和字段
枚举类型也可以有构造方法和字段。每个枚举常量都是枚举类的一个实例,因此它们可以关联一些状态。
public enum Day {
MONDAY("Monday"),
TUESDAY("Tuesday"),
// ... 其他几天
SUNDAY("Sunday");
private final String name;
Day(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
在这个例子中,每个Day枚举常量都有一个与之关联的name字段,并通过构造方法初始化。
枚举与switch语句
枚举常量常与switch语句一起使用,因为它提供了类型安全的比较。
Color color = Color.RED;
switch (color) {
case RED:
System.out.println("The color is red.");
break;
case GREEN:
System.out.println("The color is green.");
break;
// ... 其他情况
default:
System.out.println("Unknown color.");
}
枚举的方法
枚举类型可以定义抽象方法和具体方法。抽象方法必须在每个枚举常量中实现,而具体方法可以在枚举类型中直接实现。
public enum Operation {
PLUS {
@Override
public int apply(int a, int b) {
return a + b;
}
},
MINUS {
@Override
public int apply(int a, int b) {
return a - b;
}
};
public abstract int apply(int a, int b);
}
在这个例子中,Operation枚举定义了一个抽象方法apply,每个枚举常量都提供了自己的实现。
内置的枚举方法
枚举类型自身包含一些内置的方法和特性,下面是一些内置的枚举方法:
1. values() 方法:
enum Color { RED, GREEN, BLUE };
for (Color c : Color.values()) {
System.out.println(c);
}
values() 返回当前枚举类型的枚举常量数组,可以用于遍历所有的枚举值。
2. valueOf(String name) 方法:
Color color = Color.valueOf("RED");
valueOf() 方法接收一个字符串参数,该参数是枚举常量的名字(即其声明时的标识符),并返回对应名字的枚举常量。如果找不到匹配的名字,则会抛出 IllegalArgumentException 异常。
- 枚举常量默认继承自 java.lang.Enum 类,这个类提供了如下的方法
方法 | 说明 |
name() | 返回枚举常量的名称(字符串形式)。 |
ordinal() | 返回枚举常量在其枚举类型中的位置索引,从0开始计数。 |
equals(Object other) 和 hashCode() | 覆盖了Object类的默认实现,以便正确比较枚举常量的相等性和哈希码。 |
例如:
enum Color {
RED, GREEN, BLUE;
}
public class Main {
public static void main(String[] args) {
Color red = Color.RED;
System.out.println(red.name()); // 输出 "RED"
System.out.println(red.ordinal()); // 输出 0
}
}
内部类中使用枚举
内部类中可以使用枚举,这两种特性可以结合在一起以满足特定的设计需求。以下是一个内部类中使用枚举的例子:
public class BankAccount {
// 定义一个内部枚举类,表示账户类型
enum AccountType {
SAVINGS,
CHECKING,
FIXED_DEPOSIT
}
// 内部类,表示账户
class Account {
private double balance;
private AccountType type;
// 构造器
Account(AccountType accountType) {
this.type = accountType;
}
// 根据账户类型提供不同服务的方法
void performAction() {
switch (type) {
case SAVINGS:
System.out.println("Performing savings account action...");
break;
case CHECKING:
System.out.println("Performing checking account action...");
break;
case FIXED_DEPOSIT:
System.out.println("Performing fixed deposit account action...");
break;
}
}
}
public static void main(String[] args) {
BankAccount bankAccount = new BankAccount();
BankAccount.Account savingsAccount = bankAccount.new Account(BankAccount.AccountType.SAVINGS);
savingsAccount.performAction();
}
}
在这个例子中,我们定义了一个名为BankAccount的类,其中包含了一个内部枚举类AccountType,用来表示银行账户的几种类型。接着,我们定义了一个内部类Account,它使用枚举AccountType来区分不同类型的账户,并根据账户类型提供不同的服务。在主方法中,我们可以创建一个内部类Account的实例,并指定其类型为枚举中的某个值,然后调用相应的方法。
枚举的集合操作
Java的EnumSet和EnumMap是专为枚举类型设计的集合类,它们提供了高效的枚举值集合和映射操作。
EnumSet<Color> colors = EnumSet.of(Color.RED, Color.GREEN);
colors.add(Color.BLUE);
for (Color color : colors) {
System.out.println(color);
}
学习建议
建议 | 描述 |
阅读官方文档 | Java官方文档提供了关于枚举的详细信息和示例,是学习的宝贵资源。 |
编写简单示例 | 从定义基本的枚举类型开始,逐渐添加构造方法、字段和方法,观察它们的行为。 |
实践应用 | 尝试在实际项目中使用枚举,例如表示状态、类型或选项。 |
探索高级特性 | 了解EnumSet和EnumMap的使用,以及如何在枚举中实现接口或继承抽象类。 |
总结
内部类主要用于封装和逻辑关联紧密的类,而枚举则是为了定义并约束一组有限的、命名良好的常量。两者都是Java语言增强代码结构和减少错误的有效工具。
猜你喜欢
- 2024-11-09 Java基础入门要学哪些 怎么掌握反射和枚举
- 2024-11-09 谈谈枚举的新用法--java java枚举类型有什么用
- 2024-11-09 Java面试基础回顾16-枚举 java面试基础知识点
- 2024-11-09 实际工作中推荐使用java枚举类型,提高开发效率#编程
- 2024-11-09 java枚举enumeration java枚举根据value获取key
- 2024-11-09 大年初二来简单聊聊java中枚举类的前世今生
- 2024-11-09 如何用枚举消除if/else?-枚举高阶用法
- 2024-11-09 干货 | 一文搞定Python 枚举 python 枚举遍历
- 2024-11-09 Scala学习九之枚举和Trait了解 枚举compareto
- 2024-11-09 java中的enum第一期:enum存在的意义
你 发表评论:
欢迎- 04-11Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- 04-11Java中你知道几种从字符串中找指定的字符的数量
- 04-11探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- 04-11Python字符串详解与示例(python字符串的常见操作)
- 04-11java正则-取出指定字符串之间的内容
- 04-11String s1 = new String("abc");这句话创建了几个字符串对象?
- 04-11java判断字符串中是否包含某个字符
- 04-11关于java开发中正确的发牌逻辑编写规范
- 最近发表
-
- Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- Java中你知道几种从字符串中找指定的字符的数量
- 探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- Python字符串详解与示例(python字符串的常见操作)
- java正则-取出指定字符串之间的内容
- String s1 = new String("abc");这句话创建了几个字符串对象?
- java判断字符串中是否包含某个字符
- 关于java开发中正确的发牌逻辑编写规范
- windows、linux如何后台运行jar(并且显示进程名)
- 腾讯大佬私人收藏,GitHub上最受欢迎的100个JAVA库,值得学习
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)