设计师可以做兼职的网站有哪些,wordpress最热文章,校园网站建设情况统计表,做个网站找别人做的吗目录 定义1#xff09;定义2#xff09;内部实现3#xff09;方法与源码 高级特性1#xff09;switch用法2#xff09;自定义传值与构造函数3#xff09;枚举实现抽象方法4#xff09;枚举注解属性5#xff09;枚举实现接口6#xff09;复合使用 总结 定义
1#xf… 目录 定义1定义2内部实现3方法与源码 高级特性1switch用法2自定义传值与构造函数3枚举实现抽象方法4枚举注解属性5枚举实现接口6复合使用 总结 定义
1定义
枚举类是Java 5引入的在Java 5之前Java并没有内置的枚举类型只能通过自定义类来实现类似枚举的功能。例如
public class EnumClass { public static final int CONSTANT1 xxx; public static final int CONSTANT2 xxx; public static final int CONSTANT3 xxx; ...
}
Java 枚举类是一种特殊类型的数据结构一般用来存储定义一些字符串数字等数据结构。枚举类中的每个常量都称为枚举常量。枚举类在Java中使用关键字enum定义。一般枚举类格式如下
public enum EnumClass { CONSTANT1, CONSTANT2, CONSTANT3, ...
}
其中EnumClass为枚举类的名称CONSTANT1、CONSTANT2、CONSTANT3等为枚举常量的名称。枚举类的引入提供了一种更简洁、更安全的定义枚举类型的方式。
枚举类可以直接在其他类中引用例如
public enum Color { RED, GREEN, BLUE
} public class ColorUtil { private ColorUtil() { } public static void main(String[] args) { Color red Color.RED; }
} 枚举类是类所以当然也可以在其他类内部定义
public class Example { public enum Color { RED, GREEN, BLUE } public static void main(String[] args) { System.out.println(Color.RED); }
} 枚举类在内部定义时可以将其作为内部类来定义也可以将其作为静态内部类来定义内部定义的枚举类可以访问外部类的成员变量和方法比如
public class Example { private static int privateVariable 10; public enum Color { RED, GREEN, BLUE; public void print() { System.out.println(name() has a value of Example.privateVariable); } } public static void main(String[] args) { Example.Color.RED.print(); }
}
这段代码运行main方法的结果为 2内部实现
我们借助IDEA中的一个反编译分析插件Jadx Class Decompiler反编译刚刚创建的Color枚举类首先安装插件如下 安装完成后右键点击需要反编译的java文件这里选择Color.java 选择01 分析字节码可以得到分析结果如下 可以看到枚举类是public和final修饰的这表示它不能像普通的类一样被继承也可以看到枚举类继承自java.lang.Enum类型并且定义了public static final修饰的三个实例变量RED GREEN BLUE这三个实例变量实际都是Color的实例对象。 此外其内部还定义了静态的values方法它会返回一个包含所有枚举实例的Color[]结构的列表以及valuesOf(String input)方法它通过传入对应的枚举常量字符串返回对应的Color实例。
3方法与源码
我们翻阅官方文档可以得知java.lang.Enum包含了如下一些方法查看Enum类源码也能看到 其中特有方法应属valuesOf()和ordinal()valuesOf()刚刚已经说明它会返回指定名称的枚举常量例如
public enum Color { RED, GREEN, BLUE;
} Color color Color.valueOf(GREEN); ordinal()方法主要是获取枚举量在枚举类中的顺序比如在上面例子中RED排在第一位ordinal()返回值为0示例如下
public static void main(String[] args) { Color red Color.RED; int ordinal red.ordinal(); // ordinal 0
}
另外在字节码分析结果中可以看到其实Enum是有构造方法的但是这个构造方法用户无法调用只有编译器可以调用我们翻阅java.lang.Enum源码可以看到 另外Enum还针对枚举常量实现了compareTo方法并且这个compareTo方法默认是根据枚举的ordinal来对比的也就是根据枚举在枚举类的声明顺序来对比的。 高级特性
1switch用法
我们知道一般在使用switch进行判断时可以使用整数、字符串甚至表达式作为条件但其实switch也支持枚举并且不需要使用枚举的引用代码示例如下
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors; public class ColorUtil { private ColorUtil() { } private static String getDescription(Color color) { switch(color) { case RED: return The color of blood; case GREEN: return The color of grass; case BLUE: return The color of the sky; default: return ; } } public static void main(String[] args) { Color red Color.RED; String description getDescription(red); System.out.println(description); }
}
运行可以得到结果如下 2自定义传值与构造函数
这个特性我本人经常使用到首先枚举类中可以定义好属性然后自定义构造函数在声明枚举类实例的时候传入对应的属性值比如在业务中可能用到的isDelete字段我们可以定义枚举类如下
import lombok.Getter; public enum IsDeleteEnum { TRUE(1, 是), FALSE(0, 否), ; //值描述 Getter private String desc; //枚举值 Getter private Integer code; IsDeleteEnum(Integer code, String desc) { this.code code; this.desc desc; }
}
这里包含了两个成员变量code和desc分别代表枚举的值和描述信息。 这个类使用了Lombok库中的Getter注解枚举值和名称可以被Getter方法直接访问。
如果上面这个还是初级版本那么下面这个高级版本则更为典型和常用我们定义了ColorEnum的枚举类它包含RED、BLUE、GREEN三个枚举值。每个枚举值都有一个值和名称并且有一个静态的Map用于根据值获取枚举常量。这个类还提供了一个公共的静态方法of()用于根据给定的值返回对应的枚举常量如果没有找到则返回null。
import lombok.Getter; import java.util.HashMap;
import java.util.Map; public enum ColorEnum { RED(0, 红色), BLUE(1, 蓝色), GREEN(2, 绿色), ; // 枚举值 Getter private Integer value; Getter private String name; private static MapInteger, ColorEnum map new HashMap(); static { for (ColorEnum r : ColorEnum.values()) { map.put(r.getValue(), r); } } ColorEnum(Integer value, String name) { this.value value; this.name name; } public static ColorEnum of(Integer value) { return map.getOrDefault(value, null); }
}
如果我想知道某个常量值x是否包含在枚举类ColorEnum 中就可以使用of()方法
public static void main(String[] args) { System.out.println(ColorEnum.of(0) null); // false System.out.println(ColorEnum.of(3) null); // true
}
运行结果如下 3枚举实现抽象方法
枚举中不只可以定义一些整数或是字符串常量甚至可以重新实现抽象方法我们定义了一个枚举类型Weekday表示一周中的每一天。每个枚举常量都重写了抽象方法doSomething()并实现了具体的业务逻辑代码如下
public enum Weekday { MONDAY { Override public void doSomething() { System.out.println(Doing something on Monday); } }, TUESDAY { Override public void doSomething() { System.out.println(Doing something on Tuesday); } }, WEDNESDAY { Override public void doSomething() { System.out.println(Doing something on Wednesday); } }, THURSDAY { Override public void doSomething() { System.out.println(Doing something on Thursday); } }, FRIDAY { Override public void doSomething() { System.out.println(Doing something on Friday); } }, SATURDAY { Override public void doSomething() { System.out.println(Doing something on Saturday); } }, SUNDAY { Override public void doSomething() { System.out.println(Doing something on Sunday); } }; // 抽象方法 public abstract void doSomething(); public static void main(String[] args) { Weekday day Weekday.MONDAY; day.doSomething(); }
}
在main函数中通过Weekday的枚举常量来调用对应的方法这样可以根据枚举常量来执行不同的操作大大增加代码的可读性和可维护性。 这段代码执行结果为 4枚举注解属性
我们自定义一个名为ColorInterface的注解用于标记字段。注解定义一个value属性类型为我们上文创建的的ColorEnum枚举类型。注解的保留策略为RetentionPolicy.RUNTIME表示在运行时可以访问到该注解。
import java.lang.annotation.*; Retention(RetentionPolicy.RUNTIME)
Target(ElementType.FIELD)
public interface ColorInterface { ColorEnum value();
}
如下面代码所示我们可以通过我们自定义的ColorInterface注解标记Flower类中的属性。main方法创建了一个Flower对象使用反射获取Flower类中的Lily字段的注解然后通过反射获取注解的value属性也就是我们的枚举
import java.lang.reflect.Field; public class Flower { ColorInterface(ColorEnum.BLUE) private int Lily; ColorInterface(ColorEnum.RED) private int rose; public static void main(String[] args) throws Exception { Flower flower new Flower(); Field field Flower.class.getDeclaredField(Lily); ColorInterface annotation field.getAnnotation(ColorInterface.class); ColorEnum value annotation.value(); System.out.println(value); }
}
代码运行如下 5枚举实现接口
Java枚举类还可以实现接口可以为枚举类型添加更多的方法和行为从而扩展枚举类的功能枚举类可以具有更多的灵活性和可扩展性此外。
public interface Animal {String makeSound();String getName();
}public enum Dog implements Animal {BROWN(Buddy, Buddy the Brown Dog),BLACK(Max, Max the Black Dog);private String name;private String sound;Dog(String name, String sound) {this.name name;this.sound sound;}Overridepublic String makeSound() {return sound;}Overridepublic String getName() {return name;}public static void main(String[] args) {Animal dog Dog.BLACK;System.out.println(dog.getName()); // 输出: MaxSystem.out.println(dog.makeSound()); // 输出: Max the Black Dog}}运行结果如下 6复合使用
前面的这些特性当然可以混在一起使用
我们定义一个接口 Reflex 里面实现了两个方法一个是可以返回颜色名称一个是可以以List形式返回它的RGB值 import java.util.List;public interface Reflex {String getColor();ListInteger getRGB();
}
然后我们重新写一下我们的 ColorEnum 枚举类里面的枚举常量对象既包含属性值又重写了方法功能比之前更强大了一些代码如下 import lombok.Getter;import java.util.HashMap;
import java.util.List;
import java.util.Map;public enum ColorEnum implements Reflex {RED(0, 红色) {Overridepublic ListInteger getRGB() {return List.of(255, 0, 0);}},BLUE(1, 蓝色) {Overridepublic ListInteger getRGB() {return List.of(0, 0, 255);}},GREEN(2, 绿色) {Overridepublic ListInteger getRGB() {return List.of(0, 255, 0);}},;// 重写Reflex接口方法Overridepublic String getColor() {return name;}Getter private Integer value; Getterprivate String name;private static MapInteger, ColorEnum map new HashMap();static { for (ColorEnum r : ColorEnum.values()) { map.put(r.getValue(), r); } } ColorEnum(Integer value, String name) { this.value value; this.name name; } public static ColorEnum of(Integer value) { return map.getOrDefault(value, null); }public static void main(String[] args) {ColorEnum colorEnum1 ColorEnum.of(2);System.out.println(colorEnum1.getName());System.out.println(colorEnum1.getColor());System.out.println(colorEnum1.getRGB());}
}
main()运行结果为 可以看到我们既返回了枚举的属性值又返回了重写方法的返回值枚举是否有其它高级用法也欢迎探索交流讨论
总结
枚举类是Java中的原始类型之一可以作为方法参数和返回值。枚举类可以通过类内的枚举常量表示特定的值。本文从源码和字节码实现的角度对枚举类的原理做了阐述并且还展示了枚举类的多种高级用法枚举类不仅可以像普通的类常量一样进行访问和使用并且可以进行多态操作不同的枚举常量可以有不同的方法实现并且可以作为方法的参数和返回值。 因此枚举类有如下优点 1.提高代码的可读性。枚举类的命名规范清晰明了能够更直观地表达代码的含义提高代码的可读性。 2.更容易的调试和维护。枚举类中的方法和变量都在一个地方方便调试和维护。 3.更好的类型安全性。使用枚举类可以提供更好的类型安全性避免了使用整数或其他类型的错误。 4.可以方便的进行多态操作枚举类支持方法的重写和多态可以方便的扩展功能。