javaenum,javaenum使用实例

本文目录一览:

java中的枚举到底有什么作用?

枚举是一种规范它规范了参数的形式,这样就可以不用考虑类型的不匹配并且显式的替代了int型参数可能带来的模糊概念 枚举像一个类,又像一个数组。

Enum作为Sun全新引进的一个关键字,看起来很象是特殊的class, 它也可以有自己的变量,可以定义自己的方法,可以实现一个或者多个接口。 当我们在声明一个enum类型时,我们应该注意到enum类型有如下的一些特征。

1.它不能有public的构造函数,这样做可以保证客户代码没有办法新建一个enum的实例。

2.所有枚举值都是public , static , final的。注意这一点只是针对于枚举值,我们可以和在普通类里面定义 变量一样定义其它任何类型的非枚举变量,这些变量可以用任何你想用的修饰符。

3.Enum默认实现了java.lang.Comparable接口。

4.Enum覆载了了toString方法,因此我们如果调用Color.Blue.toString()默认返回字符串”Blue”.

5.Enum提供了一个valueOf方法,这个方法和toString方法是相对应的。调用valueOf(“Blue”)将返回Color.Blue.因此我们在自己重写toString方法的时候就要注意到这一点,一把来说应该相对应地重写valueOf方法。

6.Enum还提供了values方法,这个方法使你能够方便的遍历所有的枚举值。

7.Enum还有一个oridinal的方法,这个方法返回枚举值在枚举类种的顺序,这个顺序根据枚举值声明的顺序而定,这里Color.Red.ordinal()返回0。

了解了这些基本特性,我们来看看如何使用它们。

1.遍历所有有枚举值. 知道了有values方法,我们可以轻车熟路地用ForEach循环来遍历了枚举值了。

for (Color c: Color.values())

System.out.println(“find value:” + c);

2.在enum中定义方法和变量,比如我们可以为Color增加一个方法随机返回一个颜色。

public enum Color {

Red,

Green,

Blue;

private static int number = Color.values().length ;

public static Color getRandomColor(){

long random = System.currentTimeMillis() % number;

switch ((int) random){

case 0:

return Color.Red;

case 1:

return Color.Green;

case 2:

return Color.Blue;

default : return Color.Red;

}

}

}

可以看出这在枚举类型里定义变量和方法和在普通类里面定义方法和变量没有什么区别。唯一要注意的只是变量和方法定义必须放在所有枚举值定义的后面,否则编译器会给出一个错误。

3.覆载(Override)toString, valueOf方法

前面我们已经知道enum提供了toString,valueOf等方法,很多时候我们都需要覆载默认的toString方法,那么对于enum我们怎么做呢。其实这和覆载一个普通class的toString方法没有什么区别。

….

public String toString(){

switch (this){

case Red:

return “Color.Red”;

case Green:

return “Color.Green”;

case Blue:

return “Color.Blue”;

default:

return “Unknow Color”;

}

}

….

这时我们可以看到,此时再用前面的遍历代码打印出来的是

Color.Red

Color.Green

Color.Blue

而不是

Red

Green

Blue.

可以看到toString确实是被覆载了。一般来说在覆载toString的时候我们同时也应该覆载valueOf方法,以保持它们相互的一致性。

4.使用构造函数

虽然enum不可以有public的构造函数,但是我们还是可以定义private的构造函数,在enum内部使用。还是用Color这个例子。

public enum Color {

Red(“This is Red”),

Green(“This is Green”),

Blue(“This is Blue”);

private String desc;

Color(String desc){

this.desc = desc;

}

public String getDesc(){

return this.desc;

}

}

这里我们为每一个颜色提供了一个说明信息, 然后定义了一个构造函数接受这个说明信息。

要注意这里构造函数不能为public或者protected, 从而保证构造函数只能在内部使用,客户代码不能new一个枚举值的实例出来。这也是完全符合情理的,因为我们知道枚举值是public static final的常量而已。

5.实现特定的接口

我们已经知道enum可以定义变量和方法,它要实现一个接口也和普通class实现一个接口一样,这里就不作示例了。

6.定义枚举值自己的方法。

前面我们看到可以为enum定义一些方法,其实我们甚至可以为每一个枚举值定义方法。这样,我们前面覆载 toString的例子可以被改写成这样。

public enum Color {

Red {

public String toString(){

return “Color.Red”;

}

},

Green {

public String toString(){

return “Color.Green”;

}

},

Blue{

public String toString(){

return “Color.Blue”;

}

};

}

从逻辑上来说这样比原先提供一个“全局“的toString方法要清晰一些。

总的来说,enum作为一个全新定义的类型,是希望能够帮助程序员写出的代码更加简单易懂,个

人觉得一般也不需要过多的使用enum的一些高级特性,否则就和简单易懂的初衷想违背了。

Java 中 Enum 如何继承?

Java Enum是不能继承的,以下是解释:

枚举类使用enum定义后在编译后默认继承了java.lang.Enum类,而不是普通的继承Object类。enum声明类继承了Serializable和Comparable两个接口。且采用enum声明后,该类会被编译器加上final声明(同String),故该类是无法继承的。枚举类的内部定义的枚举值就是该类的实例(且必须在第一行定义,当类初始化时,这些枚举值会被实例化)。

Java 5新增的enum关键词,可以定义枚举类。该类是一个特殊的类,可以定义自己的field、方法、可以实现接口,也可以定义自己的构造器。

enum在java中是什么意思

Enum 类型的介绍

枚举类型(Enumerated Type) 很早就出现在编程语言中,它被用来将一组类似的值包含到一种类型当中。而这种枚举类型的名称则会被定义成独一无二的类型描述符,在这一点上和常量的定义相似。不过相比较常量类型,枚举类型可以为申明的变量提供更大的取值范围。

举个例子来说明一下,如果希望为彩虹描绘出七种颜色,你可以在 Java 程序中通过常量定义方式来实现。

清单 1. 常量定义

Public static class RainbowColor { 

    

    // 红橙黄绿青蓝紫七种颜色的常量定义

    public static final int RED = 0; 

    public static final int ORANGE = 1; 

    public static final int YELLOW = 2; 

    public static final int GREEN = 3; 

    public static final int CYAN = 4; 

    public static final int BLUE = 5; 

    public static final int PURPLE = 6; 

 }

使用的时候,你可以在程序中直接引用这些常量。但是,这种方式还是存在着一些问题。

类型不安全

由于颜色常量的对应值是整数形,所以程序执行过程中很有可能给颜色变量传入一个任意的整数值,导致出现错误。

没有命名空间

由于颜色常量只是类的属性,当你使用的时候不得不通过类来访问。

一致性差

因为整形枚举属于编译期常量,所以编译过程完成后,所有客户端和服务器端引用的地方,会直接将整数值写入。这样,当你修改旧的枚举整数值后或者增加新的枚举值后,所有引用地方代码都需要重新编译,否则运行时刻就会出现错误。

类型无指意性

由于颜色枚举值仅仅是一些无任何含义的整数值,如果在运行期调试时候,你就会发现日志中有很多魔术数字,但除了程序员本身,其他人很难明白其奥秘。

如何定义 Enum 类型

为了改进 Java 语言在这方面的不足弥补缺陷,5.0 版本 SDK 发布时候,在语言层面上增加了枚举类型。枚举类型的定义也非常的简单,用 enum 关键字加上名称和大括号包含起来的枚举值体即可,例如上面提到的彩虹颜色就可以用新的 enum 方式来重新定义:

enum RainbowColor { RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, PURPLE }

从上面的定义形式来看,似乎 Java 中的枚举类型很简单,但实际上 Java 语言规范赋予枚举类型的功能非常的强大,它不仅是简单地将整形数值转换成对象,而是将枚举类型定义转变成一个完整功能的类定义。这种类型定义的扩展允许开发者给枚举类型增加任何方法和属性,也可以实现任意的接口。另外,Java 平台也为 Enum 类型提供了高质量的实现,比如默认实现 Comparable 和 Serializable 接口,让开发者一般情况下不用关心这些细节。

回到本文的主题上来,引入枚举类型到底能够给我们开发带来什么样好处呢?一个最直接的益处就是扩大 switch 语句使用范围。5.0 之前,Java 中 switch 的值只能够是简单类型,比如 int、byte、short、char, 有了枚举类型之后,就可以使用对象了。这样一来,程序的控制选择就变得更加的方便,看下面的例子:

清单 2. 定义 Enum 类型

// 定义一周七天的枚举类型

 public enum WeekDayEnum { Mon, Tue, Wed, Thu, Fri, Sat, Sun } 

 // 读取当天的信息

 WeekDayEnum today = readToday(); 

 

 // 根据日期来选择进行活动

 switch(today) { 

  Mon: do something; break; 

  Tue: do something; break; 

  Wed: do something; break; 

  Thu: do something; break; 

  Fri: do something; break; 

  Sat: play sports game; break; 

  Sun: have a rest; break; 

 }

对于这些枚举的日期,JVM 都会在运行期构造成出一个简单的对象实例一一对应。这些对象都有唯一的 identity,类似整形数值一样,switch 语句就根据此来进行执行跳转。

如何定制 Enum 类型

除了以上这种最常见的枚举定义形式外,如果需要给枚举类型增加一些复杂功能,也可以通过类似 class 的定义来给枚举进行定制。比如要给 enum 类型增加属性,可以像下面这样定义:

清单 3. 定制枚举类型

// 定义 RSS(Really Simple Syndication) 种子的枚举类型

 public enum NewsRSSFeedEnum { 

    // 雅虎头条新闻 RSS 种子

    YAHOO_TOP_STORIES(“”), 

    

    //CBS 头条新闻 RSS 种子

    CBS_TOP_STORIES(“”), 

    

    // 洛杉矶时报头条新闻 RSS 种子

    LATIMES_TOP_STORIES(“”); 

        

    // 枚举对象的 RSS 地址的属性

    private String rss_url; 

        

    // 枚举对象构造函数

    private NewsRSSFeedEnum(String rss) { 

        this.rss_url = rss; 

    } 

        

    // 枚举对象获取 RSS 地址的方法

    public String getRssURL() { 

        return this.rss_url; 

    } 

 }

上面头条新闻的枚举类型增加了一个 RSS 地址的属性 , 记录头条新闻的访问地址。同时,需要外部传入 RSS 访问地址的值,因而需要定义一个构造函数来初始化此属性。另外,还需要向外提供方法来读取 RSS 地址。

如何避免错误使用 Enum

不过在使用 Enum 时候有几个地方需要注意:

enum 类型不支持 public 和 protected 修饰符的构造方法,因此构造函数一定要是 private 或 friendly 的。也正因为如此,所以枚举对象是无法在程序中通过直接调用其构造方法来初始化的。

定义 enum 类型时候,如果是简单类型,那么最后一个枚举值后不用跟任何一个符号;但如果有定制方法,那么最后一个枚举值与后面代码要用分号’;’隔开,不能用逗号或空格。

由于 enum 类型的值实际上是通过运行期构造出对象来表示的,所以在 cluster 环境下,每个虚拟机都会构造出一个同义的枚举对象。因而在做比较操作时候就需要注意,如果直接通过使用等号 ( ‘ == ’ ) 操作符,这些看似一样的枚举值一定不相等,因为这不是同一个对象实例。

看下面的这个例子:

清单 4. 避免错误使用 Enum 示例

// 定义一个一周七天的枚举类型

 package example.enumeration.codes; 

 public enum WeekDayEnum { 

    Mon(1), Tue(2), Wed(3), Thu(4), Fri(5), Sat(6), Sun(7); 

    private int index; 

    WeekDayEnum(int idx) { 

        this.index = idx; 

    } 

    public int getIndex() { 

        return index; 

    } 

 }

// 客户端程序,将一个枚举值通过网络传递给服务器端

 package example.enumeration.codes; 

 import java.io.IOException; 

 import java.io.ObjectOutputStream; 

 import java.io.OutputStream; 

 import java.net.InetSocketAddress; 

 import java.net.Socket; 

 import java.net.UnknownHostException; 

 public class EnumerationClient { 

    public static void main(String… args) throws UnknownHostException, IOException { 

        Socket socket = new Socket(); 

  // 建立到服务器端的连接

        socket.connect(new InetSocketAddress(“127.0.0.1”, 8999)); 

    // 从连接中得到输出流

        OutputStream os = socket.getOutputStream(); 

        ObjectOutputStream oos = new ObjectOutputStream(os); 

  // 将星期五这个枚举值传递给服务器端

        oos.writeObject(WeekDayEnum.Fri); 

        oos.close(); 

        os.close(); 

        socket.close(); 

    } 

 } 

 // 服务器端程序,将从客户端收到的枚举值应用到逻辑处理中

 package example.enumeration.codes; 

 import java.io.*; 

 import java.net.ServerSocket; 

 import java.net.Socket; 

 public class EnumerationServer { 

    public static void main(String… args) throws IOException, ClassNotFoundException { 

        ServerSocket server = new ServerSocket(8999); 

  // 建立服务器端的网络连接侦听

        Socket socket = server.accept(); 

  // 从连接中获取输入流

        InputStream is = socket.getInputStream(); 

        ObjectInputStream ois = new ObjectInputStream(is); 

  // 读出客户端传递来的枚举值

        WeekDayEnum day = (WeekDayEnum) ois.readObject(); 

  // 用值比较方式来对比枚举对象

        if (day == WeekDayEnum.Fri) { 

            System.out.println(“client Friday enum value is same as server’s”); 

        } else if (day.equals(WeekDayEnum.Fri)) { 

            System.out.println(“client Friday enum value is equal to server’s”); 

        } else { 

            System.out.println(“client Friday enum value is not same as server’s”); 

        } 

        

  // 用 switch 方式来比较枚举对象

        switch (day) { 

            case Mon: 

                System.out.println(“Do Monday work”); 

                break; 

            case Tue: 

                System.out.println(“Do Tuesday work”); 

                break; 

            case Wed: 

                System.out.println(“Do Wednesday work”); 

                break; 

            case Thu: 

                System.out.println(“Do Thursday work”); 

                break; 

            case Fri: 

                System.out.println(“Do Friday work”); 

                break; 

            case Sat: 

                System.out.println(“Do Saturday work”); 

                break; 

            case Sun: 

                System.out.println(“Do Sunday work”); 

                break; 

            default: 

                System.out.println(“I don’t know which is day”); 

                break; 

        } 

        

        ois.close(); 

        is.close(); 

        socket.close(); 

    } 

 }

打印结果如下:

client Friday enum value is same as server’s

Do Friday work

通过程序执行结果,我们能够发现在分布式条件下客户端和服务端的虚拟机上都生成了一个枚举对象,即使看起来一样的 Fri 枚举值,如果使用等号‘ == ’进行比较的话会出现不等的情况。而 switch 语句则是通过 equal 方法来比较枚举对象的值,因此当你的枚举对象较复杂时候,你就需要小心 override 与比较相关的方法,防止出现值比较方面的错误。

Enum 相关工具类

JDK5.0 中在增加 Enum 类的同时,也增加了两个工具类 EnumSet 和 EnumMap,这两个类都放在 java.util 包中。EnumSet 是一个针对枚举类型的高性能的 Set 接口实现。EnumSet 中装入的所有枚举对象都必须是同一种类型,在其内部,是通过 bit-vector 来实现,也就是通过一个 long 型数。EnumSet 支持在枚举类型的所有值的某个范围中进行迭代。回到上面日期枚举的例子上:

enum WeekDayEnum { Mon, Tue, Wed, Thu, Fri, Sat, Sun }

你能够在每周七天日期中进行迭代,EnumSet 类提供一个静态方法 range 让迭代很容易完成:

for(WeekDayEnum day : EnumSet.range(WeekDayEnum.Mon, WeekDayEnum.Fri)) { 

     System.out.println(day); 

 }

打印结果如下:

Mon 

 Tue 

 Wed 

 Thu 

 Fri

EnumSet 还提供了很多个类型安全的获取子集的 of 方法,使你很容易取得子集:

EnumSetWeekDayEnum subset = EnumSet.of(WeekDayEnum.Mon, WeekDayEnum.Wed); 

      for (WeekDayEnum day : subset) { 

          System.out.println(day);  

      }

打印结果如下:

Mon 

 Wed

与 EnumSet 类似,EnumMap 也是一个高性能的 Map 接口实现,用来管理使用枚举类型作为 keys 的映射表,内部是通过数组方式来实现。EnumMap 将丰富的和安全的 Map 接口与数组快速访问结合到一起,如果你希望要将一个枚举类型映射到一个值,你应该使用 EnumMap。看下面的例子:

清单 5. EnumMap 示例

// 定义一个 EnumMap 对象,映射表主键是日期枚举类型,值是颜色枚举类型

 private static MapWeekDayEnum, RainbowColor schema = 

            new EnumMapWeekDayEnum, RainbowColor(WeekDayEnum.class); 

    

 static{ 

    // 将一周的每一天与彩虹的某一种色彩映射起来

    for (int i = 0; i  WeekDayEnum.values().length; i++) { 

        schema.put(WeekDayEnum.values()[i], RainbowColor.values()[i]); 

    } 

 } 

 System.out.println(“What is the lucky color today?”); 

 System.out.println(“It’s ” + schema.get(WeekDayEnum.Sat));

当你询问周六的幸运色彩时候,会得到蓝色:

清单 6. 运行结果

What is the lucky color today?

It’s BLUE

结束语

Enum 类型提出给 JAVA 编程带了了极大的便利,让程序的控制更加的容易,也不容易出现错误。所以在遇到需要控制程序流程时候,可以多想想是否可以利用 enum 来实现。

enum是java关键字吗?

enum是Java的关键字,Java的关键字如下:

abstract 表明类或者成员方法具有抽象属性

assert 用来进行程序调试

boolean 基本数据类型之一,布尔类型

break 提前跳出一个块

byte 基本数据类型之一,字节类型

case 用在switch语句之中,表面其中的一个分支

catch 用在异常处理中,用来捕捉异常

char 基本数据类型之一,字符类型

class 类

const 保留关键字,没有具体含义

continue 回到一个块的开始处

default 默认,例如,用在switch语句中,表明一个默认的分支

do 用在do-while循环结构中

double 基本数据类型之一,双精度浮点数类型

else 用在条件语句中,表明当条件不成立时的分支

enum 枚举

extends 表明一个类型是另一个类型的子类型,这里常见的类型有类和接口

final 用来说明最终属性,表明一个类不能派生出子类,或者成员方法不能被覆盖,或者成员域的值不能被改变

finally 用于处理异常情况,用来声明一个基本肯定会被执行到的语句块

float 基本数据类型之一,单精度浮点数类型

for 一种循环结构的引导词

goto 保留关键字,没有具体含义

if 条件语句的引导词

implements 表明一个类实现了给定的接口

import 表明要访问指定的类或包

instanceof 用来测试一个对象是否是指定类型的实例对象

int 基本数据类型之一,整数类型

interface 接口

long 基本数据类型之一,长整数类型

native 用来声明一个方法是由与计算机相关的语言(如C/C++/FORTRAN语言)实现的

new 用来创建新实例对象

package 包

private 一种访问控制方式:私用模式

protected 一种访问控制方式:保护模式

public 一种访问控制方式:共用模式

return 从成员方法中返回数据

short 基本数据类型之一,短整数类型

static 表明具有静态属性

strictfp 用来声明FP_strict(单精度或双精度浮点数)表达式遵循IEEE 754算术规范

super 表明当前对象的父类型的引用或者父类型的构造方法

switch 分支语句结构的引导词

sychronized 表明一段代码需要同步执行

this 指向当前实例对象的引用

throw 抛出一个异常

throws 声明在当前定义的成员方法中所有需要抛出的异常

transient 声明不用序列化的成员域

try 尝试一个可能抛出异常的程序块

void 声明当前成员方法没有返回值

volatile 表明两个或者多个变量必须同步地发生变化

while 用在循环结构中

原创文章,作者:GQOD,如若转载,请注明出处:https://www.506064.com/n/134867.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
GQODGQOD
上一篇 2024-10-04 00:08
下一篇 2024-10-04 00:08

相关推荐

  • Python生成随机数的应用和实例

    本文将向您介绍如何使用Python生成50个60到100之间的随机数,并将列举使用随机数的几个实际应用场景。 一、生成随机数的代码示例 import random # 生成50个6…

    编程 2025-04-29
  • 如何在dolphinscheduler中运行chunjun任务实例

    本文将从多个方面对dolphinscheduler运行chunjun任务实例进行详细的阐述,包括准备工作、chunjun任务配置、运行结果等方面。 一、准备工作 在运行chunju…

    编程 2025-04-28
  • Python存为JSON的方法及实例

    本文将从以下多个方面对Python存为JSON做详细的阐述。 一、JSON简介 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅…

    编程 2025-04-27
  • 分析if prefixoverrides="and |or"的用法与实例

    if语句是编程语言中最为基础和常见的控制流语句,而prefixoverrides是if语句的一个重要属性。其中,prefixoverrides的常见取值为and和or。那么,这两者…

    编程 2025-04-27
  • Tanimoto系数用法介绍及实例

    本文将详细讲解Tanimoto系数的定义和使用方法,并提供相关实例代码以供参考。 一、Tanimoto系数概述 Tanimoto系数也称为Jaccard系数,是计算两个集合相似度的…

    编程 2025-04-27
  • C#可变参数的应用与实例

    一、可变参数的概念 可变参数是C#中的一个特性,它允许定义一个参数数量不确定的方法,也称作变长参数,即方法内传递的参数个数可以动态变化。使用可变参数,可以简化方法的重载,增加函数的…

    编程 2025-04-25
  • Modbus RTU通讯实例详解

    一、Modbus RTU通讯是什么? Modbus RTU通讯是一种串行通讯协议,广泛应用于工业自动化领域。通过Modbus RTU通讯协议,能够实现在不同设备之间的数据交换。 在…

    编程 2025-04-20
  • JS确认框confirm用法实例

    一、简介 JS的确认框confirm是常用的弹窗功能之一,常用于提示用户是否执行某项操作。例如,在用户点击删除按钮时,通常会弹出确认框,询问用户是否确认删除。本文将从多个方面进行详…

    编程 2025-04-18
  • 马氏距离计算实例详解

    马氏距离是一种常见的数据分析算法,主要用于测量两个样本集的相似度。相较于欧几里得距离,马氏距离考虑了不同特征之间的相关性,并使用协方差矩阵来对特征进行权重调整。本文将深入探讨如何使…

    编程 2025-04-13
  • WSLShutdown——一个Windows应用程序,用于关闭WLS实例

    一、介绍 WSLShutdown是一个小型的Windows应用程序,支持关闭当前WLS实例,或者全部关闭已经在运行的WLS实例。WLS是Windows Subsystem for …

    编程 2025-04-12

发表回复

登录后才能评论