`
gyht0808
  • 浏览: 116081 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

神奇的java枚举

    博客分类:
  • Java
阅读更多
除了不能继承自一个enum之外,基本上可以将enum看做一个常规的类,即可以添加方法,可以有main()方法,可以定义构造器
package com.myjava.testenum;
/** 
 * @author Kaili 
 * @date 创建时间:2009-10-14 下午10:05:07 
 * @version
 */
public enum TestEnum{
	
	A,
	B("First");
	private String description;
	//默认构造器
	private TestEnum(){		
	}
	//带参数的构造器
	private TestEnum(String description){
		this.description = description;
	}
	
	//覆盖enum方法
	public String toString(){
		String id = name();
		String lower = id.toLowerCase();
		return id + "(" + lower + ")";
	}
	
	public String getDescription(){
		return description;
	}
	public static void main(String[] args){
		for(TestEnum te : TestEnum.values()){
			System.out.println(te + ":" + te.getDescription());
		}
	}
}

上面提到了values()方法,但是通过研究enum的源代码发现,并没有此方法,我们利用反射机制,验证一下
import java.lang.reflect.*;
import java.util.*;
import net.mindview.util.*;

enum Explore {
	HERE, THERE
}

public class Reflection {
	// 分析class,获得此类的接口,基类,包含的方法
	public static Set<String> analyze(Class<?> enumClass) {
		System.out.println("正在分析"+enumClass);
		System.out.print("实现的借口有:");
		//遍历依赖的接口
		for (Type t : enumClass.getGenericInterfaces())
			System.out.print(t + ";   ");
		System.out.println();
		//获得基类
		System.out.println("此Class的超类: " + enumClass.getSuperclass());
		System.out.print("此Class包含的方法: ");
		Set<String> methods = new TreeSet<String>();
		//遍历包含的方法,并添加到一个Set集合
		for (Method m : enumClass.getMethods())
			methods.add(m.getName());
		System.out.println(methods);
		//返回所有方法
		return methods;
	}

	public static void main(String[] args) {
		Set<String> exploreMethods = analyze(Explore.class);
		System.out.println("-------------------------------------------");
		Set<String> enumMethods = analyze(Enum.class);
		//验证子类是不是包含父类所有方法
		System.out.println("子类是不是包含父类所有方法: " + exploreMethods.containsAll(enumMethods));
		System.out.print("子类移除父类的所有方法后,剩下的方法 ");
		exploreMethods.removeAll(enumMethods);
		System.out.println(exploreMethods);
	}
}

输出结果
引用
正在分析class enumerated.Explore
实现的借口有:
此Class的超类: class java.lang.Enum
此Class包含的方法: [compareTo, equals, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, values, wait]
-------------------------------------------
正在分析class java.lang.Enum
实现的借口有:java.lang.Comparable<E>;   interface java.io.Serializable;  
此Class的超类: class java.lang.Object
此Class包含的方法: [compareTo, equals, getClass, getDeclaringClass, hashCode, name, notify, notifyAll, ordinal, toString, valueOf, wait]
子类是不是包含父类所有方法: true
子类移除父类的所有方法后,剩下的方法 [values]

由此可以发现values()方法是由编译器添加的static方法,顺便说下,编译器还添加了一个valueOf()方法
如果你将enum实例向上转型为Enum,那么values()方法就不可访问了,但是我们可以使用Class的getEnumConstants()方法(注:如果此 Class 对象不表示枚举类型,则返回枚举类的元素或 null)

因为enum都集成Enum类,由于java不支持多继承,所以enum不能再集成其他类,但是可以同时实现一个或多个接口

用enum实现接口的方法实现一个菜单管理
public enum Meal2 {
	// 利用构造器初始化
	APPETIZER(Food.Appetizer.class), MAINCOURSE(Food.MainCourse.class), DESSERT(
			Food.Dessert.class), COFFEE(Food.Coffee.class);
	private Food[] values;

	private Meal2(Class<? extends Food> kind) {
		values = kind.getEnumConstants();
	}

	public interface Food {
		// 定义开胃菜
		enum Appetizer implements Food {
			SALAD, SOUP, SPRING_ROLLS;
		}

		// 定义主菜
		enum MainCourse implements Food {
			LASAGNE, BURRITO, PAD_THAI, LENTILS, HUMMOUS, VINDALOO;
		}

		// 定义甜点
		enum Dessert implements Food {
			TIRAMISU, GELATO, BLACK_FOREST_CAKE, FRUIT, CREME_CARAMEL;
		}

		// 定义咖啡
		enum Coffee implements Food {
			BLACK_COFFEE, DECAF_COFFEE, ESPRESSO, LATTE, CAPPUCCINO, TEA, HERB_TEA;
		}
	}
}

Enum关于常量定义的使用举例:
import java.util.*;
import java.text.*;

public enum ConstantSpecificMethod {
  DATE_TIME {
	  //实现抽象方法
    String getInfo() {
      return
        DateFormat.getDateInstance().format(new Date());
    }
  },
  CLASSPATH {
    String getInfo() {
      return System.getenv("CLASSPATH");
    }
  },
  VERSION {
    String getInfo() {
      return System.getProperty("java.version");
    }
  };
  //定义一个抽象方法
  abstract String getInfo();
  public static void main(String[] args) {
    for(ConstantSpecificMethod csm : values())
      System.out.println(csm.getInfo().length());
  }
}
分享到:
评论
27 楼 whxhz 2010-10-11  
我还是比较喜欢用enum的,总感觉可以把一大堆相关的常量定义归为一类,多个开发者一起使用,有约束,不会乱套
26 楼 woshihlp 2009-10-23  
呃。。我觉得 控制器 常用的参数 用枚举比较合适
各位能不能说下还有哪些场合适合用枚举?
25 楼 icewubin 2009-10-18  
我来举个例子,例如那个values()方法只能用在具体的枚举类,如果自己写通用工具类需要通过其他方法遍历:
    public static <T> void test(Class<T> cls) {
        for (T enumType : (T[]) cls.getEnumConstants()) {   
            System.out.println(enumType);   
        }   
    }  
24 楼 RednaxelaFX 2009-10-18  
shishuwu 写道
反编译一个自定义Enum类,可以看到它其实就是一个继承Enum的final class,里面值就是一个静态实例
package enumTest;

public enum Fruit {
	APPLE;
}

反编译结果:
package enumTest;


public final class Fruit extends Enum
{

    private Fruit(String s, int i)
    {
        super(s, i);
    }

    public static Fruit[] values()
    {
        Fruit afruit[];
        int i;
        Fruit afruit1[];
        System.arraycopy(afruit = ENUM$VALUES, 0, afruit1 = new Fruit[i = afruit.length], 0, i);
        return afruit1;
    }

    public static Fruit valueOf(String s)
    {
        return (Fruit)Enum.valueOf(enumTest/Fruit, s);
    }

    public static final Fruit APPLE;
    private static final Fruit ENUM$VALUES[];

    static 
    {
        APPLE = new Fruit("APPLE", 0);
        ENUM$VALUES = (new Fruit[] {
            APPLE
        });
    }
}



可以用枚举来写单例类,比较方便
package enumTest;

public enum Singleton {
	INSTANCE;
	public void doXX(){
		// do something
	}
	
	public static void main(String[] args) {
		Singleton.INSTANCE.doXX();
	}
}

这个反编译的结果相对实际情况来说就是杯具啊……Java用擦除法实现泛型所引发的杯具。
enum的声明展开后应该是public final class Fruit extends Enum<Fruit>才对。Enum自身是public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable。
23 楼 gyht0808 2009-10-18  
flashing 写道
我也觉得java的enum不如c和c#那种简单实用……
这个事情郁闷我很久了。

我觉得,可能java设计的enum有点class的感觉,所以有点差不多的感觉,大家就很少会去用他了
22 楼 flashing 2009-10-18  
我也觉得java的enum不如c和c#那种简单实用……
这个事情郁闷我很久了。
21 楼 shishuwu 2009-10-17  
反编译一个自定义Enum类,可以看到它其实就是一个继承Enum的final class,里面值就是一个静态实例
package enumTest;

public enum Fruit {
	APPLE;
}

反编译结果:
package enumTest;


public final class Fruit extends Enum
{

    private Fruit(String s, int i)
    {
        super(s, i);
    }

    public static Fruit[] values()
    {
        Fruit afruit[];
        int i;
        Fruit afruit1[];
        System.arraycopy(afruit = ENUM$VALUES, 0, afruit1 = new Fruit[i = afruit.length], 0, i);
        return afruit1;
    }

    public static Fruit valueOf(String s)
    {
        return (Fruit)Enum.valueOf(enumTest/Fruit, s);
    }

    public static final Fruit APPLE;
    private static final Fruit ENUM$VALUES[];

    static 
    {
        APPLE = new Fruit("APPLE", 0);
        ENUM$VALUES = (new Fruit[] {
            APPLE
        });
    }
}



可以用枚举来写单例类,比较方便
package enumTest;

public enum Singleton {
	INSTANCE;
	public void doXX(){
		// do something
	}
	
	public static void main(String[] args) {
		Singleton.INSTANCE.doXX();
	}
}
20 楼 Feiing 2009-10-16  
night_stalker 写道
大部分场景字符串就够了 —— 直白不折腾、读程序一看就懂。
性能关键的地方,不如用整数位运算。

所以枚举基本没用 …… scala 就没有枚举。

我觉得这是基于人性本恶假定的设计 —— 程序员很坏,一定会想办法写错,能做成选择题就不做成填空题。这种限定设计有时可以提高代码安全,但有时也会让人很不爽,结果就是反而降低了开发效率和代码质量。



这么说就错了, Enum 与 String 比有两大优势

1. 类型安全,  不会出现非法参数
2. Enum 本身就是个普通的 class, 可以有很多自定义方法用来实现不同的功能,用 String 就必须借助于一些 helper 方法, 这对于静态语言是很重要的特性, 看一下 java.util.concurrent.TimeUnit :

   NANOSECONDS {
        public long toNanos(long d)   { return d; }
        public long toMicros(long d)  { return d/(C1/C0); }
        public long toMillis(long d)  { return d/(C2/C0); }
        public long toSeconds(long d) { return d/(C3/C0); }
        public long toMinutes(long d) { return d/(C4/C0); }
        public long toHours(long d)   { return d/(C5/C0); }
        public long toDays(long d)    { return d/(C6/C0); }
        public long convert(long d, TimeUnit u) { return u.toNanos(d); }
        int excessNanos(long d, long m) { return (int)(d - (m*C2)); }
    },

19 楼 Feiing 2009-10-16  
myreligion 写道
enum就是一个废品!还不如简单的做成像C那样的实用,想ORM存储到数据库都困难,变态的SUN公司。。。



无知者无畏

@Enumrated(String)
private EnumType enumType;
18 楼 fujohnwang 2009-10-16  
night_stalker 写道
大部分场景字符串就够了 —— 直白不折腾、读程序一看就懂。
性能关键的地方,不如用整数位运算。

所以枚举基本没用 …… scala 就没有枚举。

我觉得这是基于人性本恶假定的设计 —— 程序员很坏,一定会想办法写错,能做成选择题就不做成填空题。这种限定设计有时可以提高代码安全,但有时也会让人很不爽,结果就是反而降低了开发效率和代码质量。


Scala没有枚举,不过,好像有case class吧?
17 楼 ziyu_1 2009-10-16  
从一开始学习java就知道枚举了,一直到工作2年,居然还是对枚举的概念很模糊.因为从来都没用到他.
16 楼 visualcatsharp 2009-10-16  
star022 写道
myreligion 写道
enum就是一个废品!还不如简单的做成像C那样的实用,想ORM存储到数据库都困难,变态的SUN公司。。。


enum是一种比较固定的有限枚举,算是一种类型的数据结构,
这种结构的数据有什么业务场景需要存入数据库吗?

小弟,将自己的知识面扩充一下吧。
看看.net里面的枚举是运用得多么的充分。
15 楼 myreligion 2009-10-16  
liugh1974 写道
java枚举虽然不完美,但还是很有用的,而且在保存数据库方面JPA 或 Hibernate都有内建的支持,不存在什么只会保存 0,1,2,3...等的情况,当然除非你本来就想要这样保存。而且应该用得也比较广了吧,至少这两年在我做的项目中,能够用的地方全都用了,而且是要求必须用。


我觉得比较好的方式是:代码里面是enum,不容易写错,数据库里面存储int/smallint之类的,可以按照enum条件查询,速度快。

不过Java的enum里面搞了很多class级别的东西,仅仅存储一个int序号很多时候根本没法顺利还原。如果要做成int条件查询的效果,就要限制enum的实现,白白增加程序员写代码时候的风险,不如语言上直接设计的简单点完了。现有enum的需求,用class就很好,两个东西很多地方都重了。
14 楼 rock 2009-10-16  
还是比较喜欢使用枚举的,感觉枚举分类比较清晰,更符合OO设计,呵呵
13 楼 goodnight 2009-10-16  
枚举我都是用于约束或者用到switch的时候定义的。
特别是switch,不过JDK7支持字符串的switch了,使用switch的时候就不用枚举了,呵呵。
12 楼 Relucent 2009-10-16  
java枚举就是个类。

不是语言本身实现的,而是编译器实现的。
11 楼 liugh1974 2009-10-16  
java枚举虽然不完美,但还是很有用的,而且在保存数据库方面JPA 或 Hibernate都有内建的支持,不存在什么只会保存 0,1,2,3...等的情况,当然除非你本来就想要这样保存。而且应该用得也比较广了吧,至少这两年在我做的项目中,能够用的地方全都用了,而且是要求必须用。
10 楼 night_stalker 2009-10-15  
大部分场景字符串就够了 —— 直白不折腾、读程序一看就懂。
性能关键的地方,不如用整数位运算。

所以枚举基本没用 …… scala 就没有枚举。

我觉得这是基于人性本恶假定的设计 —— 程序员很坏,一定会想办法写错,能做成选择题就不做成填空题。这种限定设计有时可以提高代码安全,但有时也会让人很不爽,结果就是反而降低了开发效率和代码质量。
9 楼 gyht0808 2009-10-15  
感谢大虾们的捧场,但是总感觉在现实开发中很少见到enum的例子,大家能不能分享下自己的经验?
8 楼 ray_linn 2009-10-15  
star022 写道
myreligion 写道
enum就是一个废品!还不如简单的做成像C那样的实用,想ORM存储到数据库都困难,变态的SUN公司。。。


enum是一种比较固定的有限枚举,算是一种类型的数据结构,
这种结构的数据有什么业务场景需要存入数据库吗?


想想你存入数据库的是什么? 一些毫无意义的符号而已,0,1,2,3,4,当你在运行报表的时候,这种语义缺乏会造成很大的困扰。比如 男=0,女=1, 最后打印报表时,0 和 1 根本毫无意义。

男女只是很简单的一个例子,复杂的应用里,有很多字典表,这些字典表必须体现出其词性才有意义。

相关推荐

    java枚举实例代码

    Java枚举(enum)是Java语言中的一种特殊数据类型,用于定义一组有限的常量,这些常量在程序中作为固定的值使用。枚举在Java中被引入,目的是为了更好地管理和使用常量,提高代码的可读性和安全性。在本实例代码中,...

    Java枚举类型Enum的用法

    Java枚举类型(Enum)是Java SE 5.0引入的一种新的数据类型,它为开发者提供了更为强大且安全的方式来表示一组常量。枚举在Java中不仅是一个类,还是一种特殊的类型,允许我们定义自己的常量集合。接下来,我们将...

    java枚举结果类、根据状态值获取枚举值

    java枚举结果类、根据状态值获取枚举值 Controller: /** 模块类型枚举 */ model.addAttribute("mType", ModuleTypeEnum.ModuleTypeShow()); ftl: value="${mType.key}:${mType.value}” &lt;/#list&gt;

    java枚举类型说明

    ### Java枚举类型详解 #### 一、引言 在Java编程语言中,枚举(Enum)作为一种重要的数据类型,在程序设计中扮演着不可或缺的角色。本文将深入探讨Java枚举类型的特性和用法,并通过具体实例说明其优势所在。枚举...

    简单总结java枚举类型

    Java枚举类型是Java语言中一种特殊的类,用于定义固定的常量集合,它提供了一种安全、类型化的方式来表示一组有限的值。枚举在Java中被引入为一个完整的类型,不同于C++中的枚举,这使得Java枚举更加强大且易于使用...

    java枚举状态机

    Java枚举(Enum)状态机是一种使用枚举类型来实现状态转换逻辑的编程技术,它在Java编程中被广泛应用于管理对象的状态变化。状态机是一种模型,用于描述一个系统或对象在不同时间点可能存在的状态以及如何从一个状态...

    java枚举类用法

    Java枚举类型(enum)是Java语言中一种特殊的类,用于定义一组固定的常量。它在许多场景下作为替代常量或单例模式的选择,提供了更安全、更易读的代码。下面我们将深入探讨Java枚举类的用法及其优势。 1. **枚举的...

    理解java枚举类型

    Java枚举类型是Java语言中的一种特殊的类,用于定义一组固定的常量集合。它在Java中扮演着重要的角色,提供了一种安全、类型化的常量表示方式,比传统的final static变量更具有优势。理解Java枚举类型对于编写高质量...

    高阶Java-Java枚举类型 enum 应用详解

    本篇文章将深入探讨Java枚举的特性、用法以及如何在实际开发中充分利用它们。 一、枚举的基本用法 1. 声明枚举类型: ```java public enum Color { RED, GREEN, BLUE } ``` 在这里,`Color`是枚举类型,`RED`, `...

    如何使用Java枚举类型

    一个关于JAVA枚举类型的MHT文件,包含JAVA枚举类型的用法,以及JDK版本的问题。

    java枚举ppt和详细代码

    Java枚举是面向对象编程中的一个重要特性,它用于定义固定的常量集合,这些常量通常代表某种特定的数据类型。在Java中,枚举提供了一种更安全、更规范的方式来处理常量,相比于传统的final static变量,枚举具有更多...

    java枚举的一个实例

    Java枚举是编程语言Java中的一个特色特性,它在类、接口和变量的定义中扮演着特殊的角色。枚举在Java中被用作一种数据类型,用于定义一组固定的常量,这些常量可以代表特定的值或状态。通过枚举,我们可以确保变量...

    Java枚举类型.pdf

    在本文中,我们将深入探讨Java枚举的定义、使用方法以及它如何改善传统使用`static final`常量的模式。 首先,让我们看看传统的`static final`常量表示枚举的方式。例如,清单1展示了如何使用`public static final`...

    列举java 枚举相关信息

    ### Java 枚举类型详解 #### 一、引言 ...通过以上的介绍,我们可以看到Java枚举类型不仅提供了类型安全的保障,还为开发者带来了极大的灵活性。合理地使用枚举类型,可以显著提高代码的质量和可维护性。

    Java枚举与设计模式

    本文详尽地论述了Java枚举与设计模式的关系

    java枚举类的属性、方法和构造方法应用实战

    Java 枚举类的属性、方法和构造方法应用实战 Java 枚举类是一种特殊的类,它拥有自己的属性、方法和构造方法。本文将详细介绍 Java 枚举类的属性、方法和构造方法应用实战,结合实例形式分析了 Java 枚举类的定义、...

    说说Java中的枚举 转 可以了,够了 包括EnumSet(Map)

    这篇博客将深入探讨Java枚举的特性和使用方法,包括`EnumSet`和`EnumMap`这两个与枚举相关的数据结构。 首先,枚举定义的基本语法是`public enum EnumName {constant1, constant2, ...}`。每个枚举常量都是`...

    java 通过反射获取枚举类,及枚举类的值,枚举类枚举实例名

    枚举(Enumeration)是Java中的一个特殊类类型,用于定义一组常量。本项目"test-enum-demo-master"显然是一个用于演示如何通过反射来操作枚举类的示例。 首先,让我们理解枚举类的基本概念。枚举类在Java中用于定义...

    全面掌握java枚举类型(enum-type)1

    全面掌握 Java 枚举类型(enum type) Java 枚举类型是一种特殊的数据类型,它可以取有限个数的明确值。枚举类型的引入解决了 int 枚举模式和 String 枚举模式的缺点,提供了类型安全性、可读性和性能等优势。 ...

    Java面试枚举从使用到原理

    本篇文章将深入探讨Java枚举的使用及其背后的原理。 一、枚举的定义与使用 1. 基本用法: 在Java中,枚举可以通过`enum`关键字来创建。例如,我们可以定义一个表示一周七天的枚举类型: ```java public enum ...

Global site tag (gtag.js) - Google Analytics