Java枚举类用法深入浅出

阅jdk并发包源码,常调用到java.util.concurrent.TimeUnit,发现如下写法有点奇怪。

public enum 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)); }
    },

}

代码只截取了一段。但是这种写法却没见过。

原来这种块级别的写法只能出现在枚举类中,而枚举在Java中是一种特殊的类。

要想了解内部原理,最简单粗暴的方法就是反编译class文件。

public enum WeekUtil {

    Monday {
        @Override
        public String toString() {
            return "星期一";
        }
        @Override
        boolean isRest() {
            return false;
        }
    },
    Tuesday {
        @Override
        public String toString() {
            return "星期二";
        }
        @Override
        boolean isRest() {
            return false;
        }
    },
    Wednesday {
        @Override
        public String toString() {
            return "星期三";
        }
        @Override
        boolean isRest() {
            return false;
        }
    },
    Thursday {
        @Override
        public String toString() {
            return "星期四";
        }
        @Override
        boolean isRest() {
            return false;
        }
    },
    Friday {
        @Override
        public String toString() {
            return "星期五";
        }
        @Override
        boolean isRest() {
            return false;
        }
    },
    Saturday {
        @Override
        public String toString() {
            return "星期六";
        }

        @Override
        boolean isRest() {
            return true;
        }
    },
    Sunday {
        @Override
        public String toString() {
            return "星期天";
        }

        @Override
        boolean isRest() {
            return true;
        }
    };

    abstract boolean isRest();
}

WeekUtil编译后产生8个class文件,其中一个WeekUtil文件,而WeekUtil$1.class实际上是匿名内部类,不明白内部类的,请看前文总结 Java内部类总结

1551942266(1).jpg

实际上进一步用javap反编译得到如下结果:


1551942381(1).jpg

很明显的看出,编译器把enum枚举类继承java.lang.Enum基类,这是Jdk默认的,每个枚举类型是final定义的常量,本文提到那种写法实际上是匿名内部类的写法,如果类型的枚举中出现抽象方法,则实例化枚举类型必须用匿名内部类的写法,因为enum类型是不允许被继承的。当然重写java.lang.Enum的方法,也必须用匿名内部类的块级写法。

实际上java.lang.Enum默认包含两个参数的构造方法,一个是枚举的字符串,一个是枚举的顺序index。

    protected Enum(String name, int ordinal) {
        this.name = name;
        this.ordinal = ordinal;
    }

你可能感兴趣的:(Java枚举类用法深入浅出)