• 静态变量、枚举、以及静态代码块的使用场景


    摘要: 静态变量、枚举、以及静态代码块的使用场景

        记得最开始写代码的时候,当使用到字符串的时候,就在使用的 地方定义一个String类型的字符串,但是后面发现在一个类中定义了很多重复的字符串【最初的阶段】。

        在sonar分析的时候,sonar建议把一个类型重复的字符串提到最上面,定义成常量来使用。后来一段时间都是这么做的。【稍有进步】

        后来,渐渐的发现其实不光是一个类的内部有重复的字符串,相邻的类中也有重复的字符串的情况。然后就把这些字符串定义到一个基类中,以业务为单位,每个业务都定义一个基类,把这些常量放到基类中,包括一些以业务为边界的公共方法,也放到基类中。然后每个业务类都继承该业务的基类。【这个是我跟一个有几年经验的前辈学习到的,算是一种进阶的处理方法】

        随后,我发现还有一些常量和方法是整个项目的公共方法,并不是以业务为边界,可以再作为一个基类提出来的。但是java是单继承的。不能继承多个基类的。然后我就在业务基类的上方,再提取一层,然后把整个项目的公共方法以及常量都放进去,然后各个业务的基类都继承自这个公共的基类。这样就更合理一点。模型如下图:

        今天,在回顾Java知识的时候,我又发现了枚举,以及静态代码块。结合枚举和静态代码块的使用场景,觉得基类中的一些常量和方法如果放成静态代码块或者枚举值的话,将更合适。

    温故而知新呀。

        我查了一下JDK的发展历史,其实在JDK1.5以前,在java编程过程中,我们通常需要定义一些固定数量的常量,通常的做法是定义一个静态常量类;但自JDK1.5之后,java引入了枚举(关键字enum,全称为 enumeration,值类型),在枚举中,我们可以把有相关性的常量分组到一个枚举类型里,枚举也比常量类有更多灵活的用法,使用枚举,可以有效的提高代码的整洁性、可读性、可维护性等等,这里简单总结一下常用的枚举用法。

    下面看一下枚举的使用场景:

    1、作为普通的常量使用,如星期、季节、颜色、城市等等;通常配合switch语句使用。

    //定义
    //周一到周天枚举
    public enum WeekEnum {
        MON,TUES,WED,THURS,FRI,SAT,SUN;
    }
    //使用
    //jdk1.7开始switch语句开始支持String类型,而jdk1.6之前只支持int,char,enum类型,使用枚举的话,能使代码的可读性大大增强
    public class TestEnum {
        public static void main(String[] args) {
            WeekEnum week = WeekEnum.TUES;
            switch (week) {
                case MON:
                    System.out.println("星期一");
                    break;
                case TUES:
                    System.out.println("星期二");
                    break;
                case WED:
                    System.out.println("星期三");
                    break;
                case THURS:
                    System.out.println("星期四");
                    break;
                case FRI:
                    System.out.println("星期五");
                    break;
                case SAT:
                    System.out.println("星期六");
                    break;
                case SUN:
                    System.out.println("星期天");
                    break;
            }
        }
    }

    2、往枚举中添加变量、构造函数、以达到灵活获取指定值的目的(注: Java 要求必须先定义 enum 实例,否则编译会报错);通常用于一些业务系统中定义一些固定值,如用于匹配db中的字段值等。我发现我最近代码中的一些常量可以使用这种方法来替换。

    //定义
    //利用构造函数将变量赋值,然后通过get方法获取指定值
     public enum CompanyEnum {
        SF("顺丰速运", 1001), YTO("圆通速递", 1002),STO("申通物流",1003),YD("韵达快运",1004),YZPY("中国邮政",1005);
        private CompanyEnum(String company, int code) {
            this.company = company;
            this.code = code;
        }
        private String company; // 公司名称
        private int code; // 公司编码
        public String getCompany() {
            return company;
        }
        public void setCompany(String company) {
            this.company = company;
        }
        public int getCode() {
            return code;
        }
        public void setCode(int code) {
            this.code = code;
        }
    }
    //使用
    //输出->1001 、 顺丰速运
    public class TestEnum {
        public static void main(String[] args) {
            System.out.println(CompanyEnum.SF.getCode());
            System.out.println(CompanyEnum.SF.getCompany());
        }
    }

    3、往枚举中添加自己特定方法,以实现自己所需的相关业务逻辑。

    //定义
    public enum CompanyEnum {
        SF("顺丰速运", 1001), YTO("圆通速递", 1002), STO("申通物流", 1003), YD("韵达快运", 1004), YZPY("中国邮政", 1005);
        private CompanyEnum(String company, int code) {
            this.company = company;
            this.code = code;
        }
        private String company; // 公司名称
        private int code; // 公司编码
        public String getCompany() {
            return company;
        }
        public void setCompany(String company) {
            this.company = company;
        }
        public int getCode() {
            return code;
        }
        public void setCode(int code) {
            this.code = code;
        }
        //根据物流公司名字获取对应的编码
        public static int getCodeByCompany(String company) {
            for (CompanyEnum c : CompanyEnum.values()) {
                if (c.getCompany().equals(company.trim())) {
                    return c.code;
                }
            }
            return 0;
        }
        //根据物流公司编码获取对应的名字
        public static String getCompanyByCode(int code) {
            for (CompanyEnum c : CompanyEnum.values()) {
                if (c.getCode() == code) {
                    return c.getCompany();
                }
            }
            return null;
        }
    }
    
    //使用
    //输出->1001 、 圆通速递 
    public class TestEnum {
        public static void main(String[] args) {
            System.out.println(CompanyEnum.getCodeByCompany("顺丰速运"));
            System.out.println(CompanyEnum.getCompanyByCode(1002));
        }
    }

    这种枚举用法,通常还可用于系统的错误码与对应的错误码描述,然后根据错误码获取错误码对应的描述。

    4. 其它用法,java中的枚举还有许多其它的用法,如重写toString()、equals()等方法,实现接口、枚举Map等等,直接给2个简单的例子吧。

    /**
    * 枚举本身的一些方法使用
    */
    public class TestEnum {
        public static void main(String[] args) {
            //返回此枚举常量的名称,继承自java.lang.Enum类,通常重写该方法以实现相关操作。输出->SF
            System.out.println(CompanyEnum.SF.toString());
            //返回此枚举常量的名称。输出->SF
            System.out.println(CompanyEnum.SF.name());
            //返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。输出->0
            System.out.println(CompanyEnum.SF.ordinal());
            //获取枚举中的常量个数。输出->5
            System.out.println(CompanyEnum.SF.values().length);
            //返回带指定名称的指定枚举类型的枚举常量。输出->顺丰速运
            System.out.println(CompanyEnum.SF.valueOf(CompanyEnum.class, "SF").getCompany());  
            //比较此枚举与指定对象的顺序;SF位置是0,YTO位置是1,结果为 0-1=-1。输出->-1
            System.out.println(CompanyEnum.SF.compareTo(CompanyEnum.YTO)); 
            //返回与此枚举常量的枚举类型相对应的 Class 对象。输出->class com.cndmss.util.CompanyEnum
            System.out.println(CompanyEnum.SF.getDeclaringClass());
            //。输出->true
            System.out.println(CompanyEnum.SF.name().equals("SF"));
            //。输出->true
            System.out.println(CompanyEnum.SF.equals(CompanyEnum.SF));
            //。输出->false
            System.out.println(CompanyEnum.SF.equals(CompanyEnum.YTO));
        }
    }
    /**
     *EnumSet、EnumMap的使用
     */
    public class TestEnum {
        public static void main(String[] args) {
             //1、 EnumSet的使用
            EnumSet<CompanyEnum> companySet = EnumSet.allOf(CompanyEnum.class);
            for (CompanyEnum company:companySet) {
                System.out.println(company.getCode() + ":" + company.getCompany());
            }
            //2、EnumMap的使用
            EnumMap<CompanyEnum, String> companyMap = new EnumMap(CompanyEnum.class);
            companyMap.put(CompanyEnum.SF, "顺丰map");
            companyMap.put(CompanyEnum.YTO, "圆通map");
            Iterator<Entry<CompanyEnum, String>> iter = companyMap.entrySet().iterator();
            while(iter.hasNext()){
                Entry<CompanyEnum, String> entry = iter.next();
                System.out.println(entry.getKey().name() + ":" + entry.getValue());
            }
        }
    }

    Java中,所有枚举类都是继承java.lang.Enum类,可以把 enum 看成是一个普通的 class,它们都可以定义一些属性和方法,因为java是单继承,所以枚举不能再继承其它类,但枚举可以实现接口。

    好早之前找的资料完了出自哪位前辈的了QAQ

  • 相关阅读:
    第一期知识点
    如何正确地停止一个线程?
    JVM知识点总览-高级Java工程师面试必备
    常见GC算法,CMS以及G1的垃圾回收过程,CMS的各个阶段哪两个是Stop the world的,CMS会不会产生碎片,G1的优势。
    深入理解分布式事务,高并发下分布式事务的解决方案
    JVM中的逃逸分析
    JVM内存初学 堆、栈、方法区
    JVM方法栈的工作过程,方法栈和本地方法栈有什么区别。
    JVM的基本结构和JVM的内存结构
    一致性hash算法应用场景、详解与实现(JAVA)
  • 原文地址:https://www.cnblogs.com/RCJL/p/8742683.html
Copyright © 2020-2023  润新知