IMHO, I doubt you how not used to enumerate

Profile


Are we the same?

Estimated that many small partners (myself included) have this situation, the self Javawhen reading the language, on the enumeration enumknowledge of this one probably a little bit , "underestimate the enemy" , that piece of content is very simple, in passing, but also in the actual process of writing code does not pay attention to use.

Yes, I am, too! Until one day I have not seen mention of code review, technical director meal was approved, I was again picked up the "Java programming ideas", the enumeration piece of knowledge and re-examine it again.


Why do we need to enumerate

It does not define the constant smell? Why have to use enumeration?

For chestnut, with regard to the B station to upload a video, for example, video generally have three states: draft , review and publication , we can define it as a static constant :

public class VideoStatus {
    
    public static final int Draft = 1; //草稿
    
    public static final int Review = 2; //审核
    
    public static final int Published = 3; //发布
}

For this single-value type static constants defined itself true, primarily at the local used is not a constraint clarity only, such as:

void judgeVideoStatus( int status ) {
    
    ...
    
}

For example, here's judgeVideoStatusintended function is passed VideoStatusone of three static constant, but because there is no constraint on the type, and therefore can pass as a intvalue are possible, the compiler does not raise any warning.

But after the enumeration type appears above this situation can be used to enumerate rigorous constraints, such as video enumeration to define the state is very simple:

public enum VideoStatus {
    Draft, Review, Published
}

But primarily at the local enumeration will have a stronger type constraints :

// 入参就有明确类型约束
void judgeVideoStatus( VideoStatus status ) {
    
    ...
    
}

So use judgeVideoStatusa function, the parameter types, the type of restraint would be clear that once passed an invalid value, the compiler will help us to check, thus avoiding potential problems.

In addition, more convenient than the enumeration constants in Cape scalability, and more elegant.


Meet the system re-enumeration

Or take the earlier "Promise me, stop if / else can you go in the world of" The example of it: for example, in the background management system, the user must have a role in that role and are generally fixed for the definition as an enumeration:

public enum UserRole {

    ROLE_ROOT_ADMIN,  // 系统管理员

    ROLE_ORDER_ADMIN, // 订单管理员

    ROLE_NORMAL       // 普通用户
}

Next, we will use this UserRoleexample to illustrate all the basic usage enumeration :

UserRole role1 = UserRole.ROLE_ROOT_ADMIN;
UserRole role2 = UserRole.ROLE_ORDER_ADMIN;
UserRole role3 = UserRole.ROLE_NORMAL;

// values()方法:返回所有枚举常量的数组集合
for ( UserRole role : UserRole.values() ) {
    System.out.println(role);
}
// 打印:
// ROLE_ROOT_ADMIN
// ROLE_ORDER_ADMIN
// ROLE_NORMAL

// ordinal()方法:返回枚举常量的序数,注意从0开始
System.out.println( role1.ordinal() ); // 打印0
System.out.println( role2.ordinal() ); // 打印1
System.out.println( role3.ordinal() ); // 打印2

// compareTo()方法:枚举常量间的比较
System.out.println( role1.compareTo(role2) ); //打印-1
System.out.println( role2.compareTo(role3) ); //打印-2
System.out.println( role1.compareTo(role3) ); //打印-2

// name()方法:获得枚举常量的名称
System.out.println( role1.name() ); // 打印ROLE_ROOT_ADMIN
System.out.println( role2.name() ); // 打印ROLE_ORDER_ADMIN
System.out.println( role3.name() ); // 打印ROLE_NORMAL

// valueOf()方法:返回指定名称的枚举常量
System.out.println( UserRole.valueOf( "ROLE_ROOT_ADMIN" ) );
System.out.println( UserRole.valueOf( "ROLE_ORDER_ADMIN" ) );
System.out.println( UserRole.valueOf( "ROLE_NORMAL" ) );

In addition, it can also be used to enumerate switchstatement, and the meaning more clear:

UserRole userRole = UserRole.ROLE_ORDER_ADMIN;
switch (userRole) {
    case ROLE_ROOT_ADMIN:  // 比如此处的意义就非常清晰了,比1,2,3这种数字好!
        System.out.println("这是系统管理员角色");
        break;
    case ROLE_ORDER_ADMIN:
        System.out.println("这是订单管理员角色");
        break;
    case ROLE_NORMAL:
        System.out.println("这是普通用户角色");
        break;
}

Custom expansion enumeration

Enumeration example shown above is very simple, just a case of a single value , while the actual project with the enumeration is often multi-value usage.

For example, I want to expand at the above UserRoleenumeration, which added character name - Role coded correspondence relationship, which is the actual project in common usage.

At this time we can customize a variety of properties, the constructor in the enumeration, and even a variety of methods:

public enum UserRole {

    ROLE_ROOT_ADMIN( "系统管理员", 000000 ),
    ROLE_ORDER_ADMIN( "订单管理员", 100000 ),
    ROLE_NORMAL( "普通用户", 200000 ),
    ;

    // 以下为自定义属性
    
    private final String roleName;  //角色名称

    private final Integer roleCode; //角色编码

    // 以下为自定义构造函数
    
    UserRole( String roleName, Integer roleCode ) {
        this.roleName = roleName;
        this.roleCode = roleCode;
    }

    // 以下为自定义方法
    
    public String getRoleName() {
        return this.roleName;
    }

    public Integer getRoleCode() {
        return this.roleCode;
    }

    public static Integer getRoleCodeByRoleName( String roleName ) {
        for( UserRole enums : UserRole.values() ) {
            if( enums.getRoleName().equals( roleName ) ) {
                return enums.getRoleCode();
            }
        }
        return null;
    }

}

From the above code in enumcan be like in general enumeration class Classdeclaration attributes, constructors and methods in the same member.


Enumeration Interface + =?

For example, in my earlier "Promise me, stop if / else take the world that can do" in talking about annoying if/elsewhen removed, it talked about how to implement interfaces allow enumeration to facilitate the completion.

This place may wish to review again:

What role can do something, it is obvious there is a corresponding relationship, we first define a common interface RoleOperation, representing different roles can do the following:

public interface RoleOperation {
    String op();  // 表示某个角色可以做哪些op操作
}

Next we will be the situation in different roles to do all by enumeration class, define an enum class RoleEnum, and let it go implement RoleOperationthe interface:

public enum RoleEnum implements RoleOperation {

    // 系统管理员(有A操作权限)
    ROLE_ROOT_ADMIN {
        @Override
        public String op() {
            return "ROLE_ROOT_ADMIN:" + " has AAA permission";
        }
    },

    // 订单管理员(有B操作权限)
    ROLE_ORDER_ADMIN {
        @Override
        public String op() {
            return "ROLE_ORDER_ADMIN:" + " has BBB permission";
        }
    },

    // 普通用户(有C操作权限)
    ROLE_NORMAL {
        @Override
        public String op() {
            return "ROLE_NORMAL:" + " has CCC permission";
        }
    };
}

In this way, at the call becomes extremely simple, single line of code on the line, what do not need if/else:

public class JudgeRole {
    public String judge( String roleName ) {
        // 一行代码搞定!之前的if/else灰飞烟灭
        return RoleEnum.valueOf(roleName).op();
    }
}

And this way, I want to expand later if conditions are just going to enumerate class plus the code can be, and do not change any old code, and is in line with the opening and closing principle !


Enumeration and design patterns

what? Enum can implement the design pattern?

Yes! Not only can but also to achieve several!

1, singleton

public class Singleton {

    // 构造函数私有化,避免外部创建实例
    private Singleton() {

    }

    //定义一个内部枚举
    public enum SingletonEnum{

        SEED;  // 唯一一个枚举对象,我们称它为“种子选手”!

        private Singleton singleton;

        SingletonEnum(){
            singleton = new Singleton(); //真正的对象创建隐蔽在此!
        }

        public Singleton getInstnce(){
            return singleton;
        }
    }

    // 故意外露的对象获取方法,也是外面获取实例的唯一入口
    public static Singleton getInstance(){
        return SingletonEnum.SEED.getInstnce(); // 通过枚举的种子选手来完成
    }
}

2, Strategy Mode

This is relatively good, for example, such as enumeration can write a policy-based mode of Math Calculator

public class Test {

    public enum Calculator {

        ADDITION {
            public Double execute( Double x, Double y ) {
                return x + y; // 加法
            }
        },

        SUBTRACTION {
            public Double execute( Double x, Double y ) {
                return x - y; // 减法
            }
        },

        MULTIPLICATION {
            public Double execute( Double x, Double y ) {
                return x * y; // 乘法
            }
        },


        DIVISION {
            public Double execute( Double x, Double y ) {
                return x/y;  // 除法
            }
        };

        public abstract Double execute(Double x, Double y);
    }
    
    public static void main(String[] args) {
        System.out.println( Calculator.ADDITION.execute( 4.0, 2.0 ) );       
        // 打印 6.0
        System.out.println( Calculator.SUBTRACTION.execute( 4.0, 2.0 ) );    
        // 打印 2.0
        System.out.println( Calculator.MULTIPLICATION.execute( 4.0, 2.0 ) ); 
        // 打印 8.0
        System.out.println( Calculator.DIVISION.execute( 4.0, 2.0 ) );       
        // 打印 2.0
    }
}

Collections devoted to enumeration

We usually are generally accustomed to using such as: HashMapand HashSetso on to the set of elements in full bloom, and for enumeration, has its special collections: EnumSetandEnumMap

1、EnumSet

EnumSetIt is dedicated to bloom enumerated type designed Settype.

Or, for example, with regard to the role of the text defined at the beginning of the enumeration as an example:

public enum UserRole {

    ROLE_ROOT_ADMIN,  // 系统管理员

    ROLE_ORDER_ADMIN, // 订单管理员

    ROLE_NORMAL       // 普通用户
}

For example, the system to a group of people, we need to see that he is a not a role in:

// 定义一个管理员角色的专属集合
EnumSet<UserRole> userRolesForAdmin 
    = EnumSet.of( 
        UserRole.ROLE_ROOT_ADMIN,
        UserRole.ROLE_ORDER_ADMIN 
    );

// 判断某个进来的用户是不是管理员
Boolean isAdmin( User user ) {
    
    if( userRoles.contains( user.getUserRole() ) )
        return true;
    
    return false;
}

2, EnumMap

Similarly, EnumMapit is specialized in full bloom for the enumeration type as keya Maptype.

For example, the system to a group of people, we need to count different roles in the end how many people have this to say:

Map<UserRole,Integer> userStatisticMap = new EnumMap<>(UserRole.class);

for ( User user : userList ) {
    Integer num = userStatisticMap.get( user.getUserRole() );
    if( null != num ) {
        userStatisticMap.put( user.getUserRole(), num+1 );
    } else {
        userStatisticMap.put( user.getUserRole(), 1 );
    }
}

Use EnumMapcan be very convenient.


to sum up

Small enumeration to play out so many things, but fortunately explore and summarize the process quite interesting, but also review a lot of knowledge, come slowly.


Published 78 original articles · won praise 631 · views 90000 +

Guess you like

Origin blog.csdn.net/wangshuaiwsws95/article/details/104915134