分享

java枚举使用

 koolboy2015 2015-08-24

Java 中一个典型的枚举类型,看似字符串值,但包含一些附加的信息,包括排序以及附加的方法可以获取枚举值的信息。

下面是一个基本的枚举类型:

1
public enum Suit { CLUBS, DIAMONDS, HEARTS, SPADES }

可增加附加信息,例如私有构造器、私有属性等,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public enum Numbers {
    One(1), Two(2), Three(3);
 
    private Numbers(int value)
    {
        this.value = value;
    }
 
    public int getValue()
    {
        return this.value;
    }
 
    private int value;
}

在上面的例子中,我们引入了 getValue() 方法,这便是枚举的行为定义。

接下来我们要做的是枚举类型对接口的继承以及实际的用途。

为了显示工作过程,我们首先做一个接口,用来实现类和数据库表的一个映射:

1
2
3
4
5
6
public interface DatabaseMapping {
    public String getType();
    public boolean isKey();
    public boolean isNullable();
    //public String name();
}

name() 方法这个时候被注释掉,待会我们会取消注释。

接下来我们创建一个新的 Java 类用以定义和数据库之间的映射关系:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Person {
    public String getFirstname() {
        return firstname;
    }
    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }
    public String getLastname() {
        return lastname;
    }
    public void setLastname(String lastname) {
        this.lastname = lastname;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    private String firstname;
    private String lastname;
    private int age;
}

然后我意识到了,其实有更好的方法来映射一个类到数据库表,上面这个例子很做作。当我们定义了映射到表的类时,我们需要定义一个独立的映射类,但实际上用枚举更好,数据库表中的字段可以是枚举的成员。

例如下面这样写不是更简单吗?

1
2
3
public enum PersonMapping {
    personId, firstname, lastname, age;
}

而且我们可以通过给枚举类型附加一些方法来实现数据库映射的细节:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public enum PersonMapping {
    personId("INTEGER"truefalse),
    firstname("TEXT"falsefalse),
    lastname("TEXT"falsefalse),
    age("INTEGER"falsefalse);
    private PersonMapping(String type, boolean key, boolean nullable )
    {
        this.type = type;
        this.key = key;
        this.nullable = nullable;
    }
    public String getType() {
        return type;
    }
    public boolean isKey() {
        return key;
    }
    public boolean isNullable() {
        return nullable;
    }
    private final String type;
    private final boolean key;
    private final boolean nullable;
}

现在我们可以使用这个枚举来迭代所有字段并创建相应的表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public String dbTableCreate(String tableName) {
    StringBuilder builder = new StringBuilder("Create table ");
    builder.append(tableName);
    builder.append("(");
    for (PersonMapping column : PersonMapping.values()) {
        builder.append(column.name());
        builder.append(" ");
        builder.append(column.getType());
        builder.append(column.isKey() ? " primary key" "");
        builder.append(", ");
    }
    builder = new StringBuilder(builder.substring(0, builder.length() - 2));
    builder.append(");");
    return builder.toString();
}

这个 PersonMapping 枚举类型看起来不错,但是它不允许我们使用不同的类到数据库的映射,因此我们需要抽象,需要接口。从上面的代码看,我们需要枚举类型两个通过的方 法:name() 和 values(),第一个方法返回当前枚举值的名字,第二个就是列出所有的枚举值。

首先,我们为枚举添加一个接口:

1
2
3
public enum PersonMapping implements MappingEnum{
    ....
}

然后注释掉我们前面提到的 name() 方法:

1
2
3
4
5
6
public interface MappingEnum {
    public String getType();
    public boolean isKey();
    public boolean isNullable();
    public String name();
}

最后我们编写一个 dbTableCreate() 方法来让其他的枚举类型可重用这个方法:

1
dbTableCreate("tableName", PersonMapping.values()));

完整的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public String dbTableCreate(String tableName, MappingEnum[] values) {
    StringBuilder builder = new StringBuilder("Create table ");
    builder.append(tableName);
    builder.append("(");
    for (MappingEnum column : values) {
        builder.append(column.name());
        builder.append(" ");
        builder.append(column.getType());
        builder.append(column.isKey() ? " primary key" "");
        builder.append(", ");
    }
    builder = new StringBuilder(builder.substring(0, builder.length() - 2));
    builder.append(");");
    return builder.toString();
}

讲解就到此结束,我们得出了一些结论:

  • 枚举类型可以存储附加的数据和方法

  • 枚举类型可通过接口来定义行为

  • 枚举类型的项行为可通过接口来访问,跟正常的 Java 类无异

  • values() 方法可用来返回接口中的一个数组


总而言之,你可以像使用普通 Java 类一样来使用枚举类型。



       Java Design Demo--枚举类型--避免嵌套过多            

    834人阅读    评论(0)    收藏    举报    

我们在初学时用过if--else的语句,也用过switch,但是你会发觉如果嵌套过多代码可读性变差。

如以下我们写过通过分数给学生成绩评级,简写后的代码如下


A示例

  1. public class Test {  

  2.       

  3.     /** 

  4.      * @param args 

  5.      */  

  6.     public static void main(String[] args) {  

  7.        int k=79;  

  8.        System.out.print(exem(k));  

  9.     }  

  10.   

  11.   public static String exem(int k)  

  12.   {  

  13.       int j=k/10;  

  14.       String str=null;  

  15.         switch (j) {  

  16.         case 9:  

  17.             str="优";  

  18.             break;  

  19.         case 8:  

  20.             str="良";  

  21.             break;  

  22.         case 7:  

  23.             str="良";  

  24.             break;  

  25.         case 6:  

  26.             str="及格";  

  27.             break;  

  28.         default:  

  29.             if(j>10||j<0)str="不存在的分数";  

  30.             if(j<6)System.out.println("不及格");  

  31.             if(k==100)str="优";  

  32.             break;  

  33.         }  

  34.         return str;  

  35.   }  

  36.   

  37. }  


B:

这样写有种面向过程的感觉,而且有点不符合人类思维,我们人类思考,首先是对优良 及格 不及格有一个概念,有知道他的范围.....然后再去判断他的分数

使用枚举进行重构:


  1. public enum Exam {  

  2.   

  3.     A(90100"优"), B(7089"良"), C(6069"及格"), D(060"不及格");  

  4.   

  5.     private int max;  

  6.     private int min;  

  7.     private String assess;  

  8.   

  9.     /*** 

  10.      * @param min 

  11.      *            最小分数段 

  12.      * @param max 

  13.      *            最大分数段 

  14.      * @param assess 

  15.      *            评级 

  16.      */  

  17.     private Exam(int min, int max, String assess) {  

  18.         this.max = max;  

  19.         this.min = min;  

  20.         this.assess = assess;  

  21.     }  

  22.   

  23.   

  24.     @Override  

  25.     public String toString() {  

  26.         // TODO Auto-generated method stub  

  27.         return "["+assess+":"+min + "~" + max+"]";  

  28.   

  29.     }  

  30.   

  31.     public static Exam get(int source) {  

  32.         for (Exam e : Exam.values()) {  

  33.   

  34.             if (source <= e.max && source >= e.min) {  

  35.                 return e;  

  36.             }  

  37.         }  

  38.         return null;  

  39.     }  

  40.   

  41.     public String getAssess() {  

  42.         return assess;  

  43.     }  

  44.   

  45.     /** 

  46.      * @param args 

  47.      */  

  48.     public static void main(String[] args) {  

  49.         System.out.println(Exam.C);  

  50.         System.out.println(Exam.get(59).getAssess());  

  51.         System.out.println(Exam.get(79).getAssess());  

  52.     }  

  53.   

  54. }  





反思,如果为了效率,我绝大多数会使用A示例,但是工程较大,就采用B示例,

因为B的可读性和修改性,扩展性,重用性都比A示例要好用的多。

相比A示例我们还知道各评级的分数段,在灵活性也变强了。

附带枚举类型的api方法


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多