浅聊java中的枚举以及关于枚举的常见面试问题

基本概念:

什么是枚举?

枚举(Enum)是一种特殊的类,它用于表示一组固定的常量。枚举从Java 5(也称为Java 1.5)开始引入,提供了一种比传统常量(如使用public static final定义的变量)更类型安全、更易读和更易维护的方式来定义一组常量。

如何定义枚举?

枚举是通过关键字enum来定义的。枚举的每一个实例都是该枚举类型的一个对象,这些对象在编译时就已经被创建,并且不能被实例化。枚举类默认继承自java.lang.Enum,但不能显式继承其他类也不能被继承,因为当枚举被编译为类时会被final修饰,但它可以实现接口)。

public enum Color {  RED, GREEN, BLUE;  
}

枚举的特性有哪些?

  1. 类型安全:枚举提供了一种类型安全的方式来表示一组常量,避免了使用整数或字符串表示常量时可能发生的错误。
  2. 自动序列化:枚举实现了java.io.Serializable接口,因此它们可以自动序列化。
  3. 单例实现:枚举是实现单例模式的最佳方式之一,因为它保证了线程安全和实例的唯一性。
  4. 包含方法和属性:枚举可以包含构造方法(必须是私有的)、字段、方法和抽象方法。

枚举的常用方法有哪些?

  • values():返回包含枚举中所有元素的数组。
  • valueOf(String name):根据枚举常量的名称返回对应的枚举常量。
  • ordinal():返回枚举常量在枚举声明中的位置(从0开始)。
  • compareTo(E o):在枚举类型上实现自然排序。这个方法允许枚举常量按照它们在枚举声明中出现的顺序进行比较。
  • name():返回枚举常量的名称,这个名称就是声明枚举常量时所用的标识符。
  • toString():默认情况下,枚举的toString()方法返回枚举常量的名称。但你也可以重写这个方法以返回更有意义的字符串表示。

枚举的日常使用示例 :

定义

枚举类是通过enum关键字来定义的。枚举类的声明类似于类,但关键字是enum而不是class

public enum Day {  SUNDAY, MONDAY, TUESDAY, WEDNESDAY,  THURSDAY, FRIDAY, SATURDAY  
}

 使用

你可以像使用其他任何类型的变量一样使用枚举常量。枚举常量在编译时就被解析为对应的枚举类型对象。

Day day = Day.MONDAY;  
System.out.println(day); // 输出 MONDAY

方法

枚举可以包含字段、方法和构造函数。但是,枚举的构造函数默认是私有的,以防止外部代码实例化枚举。 

public enum Color {  RED("红色"), GREEN("绿色"), BLUE("蓝色");  private final String description;  Color(String description) {  this.description = description;  }  public String getDescription() {  return this.description;  }  
}  System.out.println(Color.RED.getDescription()); // 输出 红色
//
// 在这个例子中,Color枚举类有一个私有字段description和一个接受字符串参数的构造函数。每个枚举常量在声明时都通过调用构造函数来初始化其description字段。

遍历

你可以使用values()方法遍历枚举的所有值。 

for (Day d : Day.values()) {  System.out.println(d);  
}

枚举与switch

枚举与switch语句配合使用非常方便,因为switch语句可以接受枚举类型作为条件表达式。 

Day day = Day.MONDAY;  switch (day) {  case MONDAY:  System.out.println("星期一");  break;  case FRIDAY:  System.out.println("星期五");  break;  default:  System.out.println("其他日子");  
}

实现接口

枚举类可以实现一个或多个接口,并定义实现这些接口所需的方法。 

interface Describable {  String describe();  
}  public enum Planet implements Describable {  MERCURY, VENUS, EARTH;  @Override  public String describe() {  // 这里只是一个简单的实现,实际上你可以根据枚举常量的不同返回不同的描述  return this.name().toLowerCase() + " is a planet";  }  
}  System.out.println(Planet.EARTH.describe()); // 输出 earth is a planet

另一种写法:

 

interface Behaviour {  void show();  
}  public enum Animal implements Behaviour {  DOG {  @Override  public void show() {  System.out.println("Woof!");  }  },  CAT {  @Override  public void show() {  System.out.println("Meow!");  }  },  BIRD {  @Override  public void show() {  System.out.println("Tweet!");  }  };  // 示例:一个静态方法,遍历所有动物并显示它们的行为  public static void showAllAnimals() {  for (Animal animal : Animal.values()) {  animal.show();  }  }  // 测试方法  public static void main(String[] args) {  showAllAnimals();  }  
}

 带构造器和方法的枚举

public enum Season {  SPRING("Spring"), SUMMER("Summer"), AUTUMN("Autumn"), WINTER("Winter");  private final String description;  // 私有构造器  Season(String description) {  this.description = description;  }  // 公开方法  public String getDescription() {  return description;  }  // 示例方法,根据季节返回活动建议  public String getActivitySuggestion() {  switch (this) {  case SPRING:  return "Go for a hike or plant a garden.";  case SUMMER:  return "Go swimming or have a picnic.";  case AUTUMN:  return "Go apple picking or take a scenic drive.";  case WINTER:  return "Go skiing or build a snowman.";  default:  return "Enjoy the season!";  }  }  // 测试方法  public static void main(String[] args) {  Season season = Season.SUMMER;  System.out.println(season.getDescription() + ": " + season.getActivitySuggestion());  }  
}

 使用枚举作为Map的键

import java.util.EnumMap;  
import java.util.Map;  public enum Day {  MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY  
}  public class WorkHours {  public static void main(String[] args) {  Map<Day, Integer> workHours = new EnumMap<>(Day.class);  workHours.put(Day.MONDAY, 8);  workHours.put(Day.TUESDAY, 8);  workHours.put(Day.WEDNESDAY, 8);  workHours.put(Day.THURSDAY, 8);  workHours.put(Day.FRIDAY, 6); // 假设周五早些下班  // 周末不工作,所以不需要设置  for (Map.Entry<Day, Integer> entry : workHours.entrySet()) {  System.out.println(entry.getKey() + ": " + entry.getValue() + " hours");  }  }  
}

枚举中的抽象方法

 

public enum Operation {  PLUS {  @Override  public double apply(double x, double y) {  return x + y;  }  },  MINUS {  @Override  public double apply(double x, double y) {  return x - y;  }  },  MULTIPLY {  @Override  public double apply(double x, double y) {  return x * y;  }  },  DIVIDE {  @Override  public double apply(double x, double y) {  if (y == 0) throw new IllegalArgumentException("Cannot divide by zero");  return x / y;  }  };  // 抽象方法  public abstract double apply(double x, double y);  // 测试方法  public static void main(String[] args) {  System.out.println(Operation.PLUS.apply(10, 5));  // 输出 15.0  System.out.println(Operation.DIVIDE.apply(10, 2)); // 输出 5.0  }  
}

EnumSet与EnumMap:

EnumSet 和 EnumMap 是 Java 集合框架中专门为枚举(enum)类型设计的两个类。它们提供了比标准集合(如 HashSet 和 HashMap)更高的性能,特别是当集合中的元素是枚举类型时。这是因为它们内部利用了枚举的固有顺序和唯一性进行优化。

EnumSet

EnumSet 是一个不包含重复元素的集合,它专门为枚举类型设计。与普通的 Set 接口实现(如 HashSet)相比,EnumSet 在空间和时间上都有显著的优势,因为它内部使用位向量来表示集合中的元素,这种表示方法非常紧凑且高效。

主要特点

  • 类型安全:由于 EnumSet 的元素是枚举类型,因此在编译时就能保证类型安全。
  • 性能高效:内部使用位向量存储元素,因此集合的创建、遍历和查找等操作都非常快。
  • 丰富的构造函数EnumSet 提供了多种构造函数,包括从类型(Class<E>)创建空集合、从现有集合创建新集合等。
  • 迭代顺序EnumSet 遍历元素的顺序是枚举的自然顺序(除非指定了另一种顺序),这对于需要按特定顺序处理枚举值的场景非常有用。

示例代码

enum Day { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY }  public class EnumSetExample {  public static void main(String[] args) {  EnumSet<Day> weekdays = EnumSet.range(Day.MONDAY, Day.FRIDAY);  for (Day day : weekdays) {  System.out.println(day);  }  }  
}

EnumMap

EnumMap 是一个映射(Map),其键是枚举类型。与普通的 Map 接口实现(如 HashMap)相比,EnumMap 提供了更高的性能,因为它内部使用数组来存储键值对并利用枚举的索引作为数组的下标

主要特点

  • 类型安全:由于 EnumMap 的键是枚举类型,因此在编译时就能保证类型安全。
  • 性能高效:内部使用数组存储键值对,使得查找、插入和删除操作都非常快。
  • 自然顺序EnumMap 遍历键的顺序是枚举的自然顺序(除非指定了另一种顺序)。
  • 内存紧凑:由于内部使用数组,且数组的大小固定为枚举类型的常量数,因此 EnumMap 的内存使用非常紧凑。

示例代码

enum Color { RED, GREEN, BLUE }  public class EnumMapExample {  public static void main(String[] args) {  EnumMap<Color, Integer> count = new EnumMap<>(Color.class);  count.put(Color.RED, 1);  count.put(Color.GREEN, 2);  count.put(Color.BLUE, 3);  for (Map.Entry<Color, Integer> entry : count.entrySet()) {  System.out.println(entry.getKey() + ": " + entry.getValue());  }  }  
}

总之,EnumSet 和 EnumMap 是 Java 集合框架中针对枚举类型优化的两个类,它们提供了类型安全、性能高效和内存紧凑的集合操作,是处理枚举类型数据时的首选集合类型。 

关于枚举的常见面试问题:

枚举如何实现单例模式?

  • 通过枚举的实例在JVM中唯一性,枚举天然就是单例的。例如,public enum Singleton { INSTANCE; }。这种方式实现单例模式既简单又安全,因为JVM保证了枚举实例的唯一性,并且枚举的构造方法是私有的,不能被外部实例化。

枚举可以继承其他类吗?

  • 枚举默认继承自java.lang.Enum类,因此不能显式继承其他类。

枚举的默认构造函数是怎样的?

  • 枚举的默认构造函数是私有的,不能显式定义访问修饰符(默认为private),且不能被外部实例化。

 枚举中的方法和属性是如何定义的?

  • 枚举中的方法和属性与普通类中的定义方式相同,但构造方法必须是私有的。

 values()valueOf(String name)方法的作用是什么?

  • values()方法返回包含枚举中所有元素的数组。
  • valueOf(String name)方法根据枚举常量的名称返回对应的枚举常量。

 枚举中的ordinal()方法有什么作用?

  • ordinal()方法返回枚举常量在枚举声明中的位置(从0开始)。

 为什么推荐使用枚举而不是静态常量?

  • 枚举提供了类型安全、自动序列化、单例实现等特性,而静态常量则不具备这些特性。此外,枚举的语义更清晰,易于理解和维护。

 这些问题涵盖了枚举的基本概念、特性、用法以及相关的设计模式,是Java枚举面试中常见的问题。在回答这些问题时,可以结合具体的代码示例和场景来解释,以增强回答的说服力和清晰度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/51499.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql 死锁 锁表的解决方法

查看那个表锁了 SHOW OPEN TABLES where In_use > 0; show processlist SELECT * FROM information_schema.INNODB_TRX; 查看锁的进程 kill 掉进程id (trx_mysql_thread_id)

pyintaller pyqt5 pytest打包后 找不到测试实例

pyintaller pyqt5 pytest打包后 找不到测试实例 1.项目目录 my_project/ ├── src/ │ ├── tests/ │ │ ├── test_example.py │ ├── main.py ├── my_project.spec2.main.py import sys from PyQt5.QtWidgets import QApplication, QWidget, QPushBut…

PCIE-Precode

Transmitter Precode Request: Precoding可以有效的降低Burst errors&#xff08;突发连续&#xff09;的影响&#xff0c;但是Bit Error Rate&#xff08;BER&#xff09;将上升为之前的两倍. ​​​​​​[FPGA 实现及PCIe IP 核知识点] PCIe为什么要增加Precoding&#xff…

Vue3:命名路由

当创建一个路由时&#xff0c;我们可以选择给路由一个 name&#xff1a; const routes [{path: /user/:username,name: profile, component: User} ] 然后我们可以使用 name 而不是 path 来传递 to 属性给 <router-link>&#xff1a; <router-link :to"{ nam…

趣味算法------拯救阿拉德大陆

目录 ​编辑 题目描述&#xff1a; 思路解析&#xff1a; 具体代码&#xff1a; 总结&#xff1a; 题目描述&#xff1a; 此时一批勇士也随之而来&#xff0c;但其能力也是参差不齐&#xff0c;我们需要挑选出最优秀的勇士来守护这片大陆。每位勇士都有属于自己的编号&am…

力扣题/回溯/全排列

全排列 力扣原题 给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] 示例 2&#xff1a; 输入&a…

网络安全售前入门04——审计类产品了解

目录 1.前言 2.数据库审计介绍 2.1产品架构功能 2.2应用场景 2.3部署形式 2.4产品价值 2.5选型依据 1.前言 为方便初接触网络安全售前工作的小伙伴了解网安行业情况,我制作一系统售前入门(安全产品,安全服务,法律法规等)文章介绍,希望能给初进网安职场的小伙伴提供…

上书房信息咨询:医疗满意度调研

随着人们生活水平的不断提高&#xff0c;医疗服务的需求日益增长。近期&#xff0c;上书房信息咨询受托完成了某市医疗市场的满意度调研&#xff0c;旨在深入了解市民对医疗服务的评价和需求&#xff0c;为提升医疗服务质量提供有力支持。 近年来&#xff0c;某市致力于推进医…

使用Oracle的PL/SQL编写自定义函数来实现split

Oracle数据库没有内置的split函数&#xff0c;但是你可以使用Oracle的PL/SQL编写自定义函数来实现类似的功能。以下是一个例子&#xff0c;展示了如何创建一个split函数&#xff0c;它将字符串按照指定的分隔符进行拆分&#xff0c;并返回一个PL/SQL表类型。 1、创建fn_split函…

国产游戏技术能否引领全球

目录 1.概述 1.1.面临的挑战 1.2.机遇 1.3.IT技术创新如何推动行业发展 2.技术解析 2.1.图形渲染技术 2.2.物理引擎 2.3.人工智能 (AI) 3.行业影响 3.1.对国内游戏开发行业的影响 3.2.IT人才需求变化 3.3.技术发展方向 4.未来展望 4.1. 发展前景 4.2. IT技术人员…

分布式基础理论——CAP理论和BASE理论

文章目录 CAP 理论BASE 理论参考资料 CAP 理论 CAP定理&#xff08;CAP theorem&#xff09;指出&#xff0c;在分布式系统中&#xff0c;设计读写操作时只能同时满足以下三个特性中的两个&#xff1a; 一致性&#xff08;Consistency&#xff09; : 所有节点访问同一份最新的…

用于目标说话人提取的统一视听线索

第二章 目标说话人提取之《Unified Audio Visual Cues for Target Speaker Extraction 》 文章目录 前言一、任务二、动机三、挑战四、方法1.总体架构2.tes网络3. 融合网络4.损失函数 五、实验评价1.数据集2.消融实验3.客观评价4.主观评价 六、结论七、知识小结 前言 语音新手…

93.WEB渗透测试-信息收集-Google语法(7)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;92.WEB渗透测试-信息收集-Google语法&#xff08;6&#xff09; • intext • intext 的作…

[数据集][目标检测]电力场景输电线导线散股检测数据集VOC+YOLO格式3890张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;3890 标注数量(xml文件个数)&#xff1a;3890 标注数量(txt文件个数)&#xff1a;3890 标注…

亲测好用,吐血整理 ChatGPT 3.5/4.0 新手使用手册~ 【2024年9月 更新】

废话不多说&#xff0c;直接分享正文~ 以下是小编为大家搜集到的最新的ChatGPT国内站&#xff0c;各有优缺点。 1、AI Plus&#xff08;稳定使用&#xff09; 推荐指数&#xff1a;⭐⭐⭐⭐⭐ yixiaai.com 该网站已经稳定运营了1年多了。2023年3月份第一批上线的网…

网络udp及ipc内存共享

大字符串找小字符串 调试 1. 信号处理函数注册&#xff1a;•一旦使用 signal 函数注册了信号处理函数&#xff0c;该函数就会一直有效&#xff0c;直到程序结束或者显式地取消注册。2. 注册多次的影响&#xff1a;•如果多次注册同一信号的处理函数&#xff0c;最后一次注册的…

PHP软件下载-安装-环境配置

.1.下载 下载地址如下 windows.php.net - /downloads/releases/ 安装包如下. .2.安装 可以在D盘或者E盘的根目录创建一个自定义目录。注意文件夹目录中不能包含中文&#xff0c;不能包含空格等特殊字符。 版本说明&#xff1a; (1)ts表示非线程安全版本。这个安装包还指明了…

Spring security 密码加密使用

一、密码加密 2011年12月21日&#xff0c;有人在网络上公开了一个包含600万个CSDN 用户资料的数据库&#xff0c;数据全部为明文储存&#xff0c;包含用户名、密码以及注册邮箱。事件发生后CSDN 在微博、官方网站等渠道发出了声明、解释说此数据库系2009 年备份所用&#xff0c…

Adobe After Effects的插件--------CC Ball Action

CC Ball Action是粒子效果器,其将2D图层变为一个个由3D小球构成的图层。它是AE内置的3D插件。 使用条件 使用该插件的图层需是2D图层。 我们以一张图片素材为例: 给图片图层添加CC Ball Action效果控件,然后新建一个摄像机(利用摄像机旋转、平移、推拉工具,方便在各个角…

OpenCV几何图像变换(6)计算反转仿射变换函数invertAffineTransform()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 反转一个仿射变换。 该函数计算由 23 矩阵 M 表示的逆仿射变换&#xff1a; [ a 11 a 12 b 1 a 21 a 22 b 2 ] \begin{bmatrix} a_{11} & a…