在此之前我一直以为枚举类型是这样
public enum Color {
RED, GREEN, BLANK, YELLOW
}
没想到可以这样写
package ink.poesy.service;
/**
* @author: WenLeiWang
* Created in 2019/11/7 9:04
*/
public enum Color {
/**
* 红色
*/
RED("春梅红","241,147,156"),
/**
* 绿色
*/
GREEN("孔雀绿","34,148,83");
private Color(String name,String rgb){
this.name = name;
this.rgb = rgb;
}
private String name;
private String rgb;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRgb() {
return rgb;
}
public void setRgb(String rgb) {
this.rgb = rgb;
}
}
今天有个哥们给我发了个代码,还能这样写
enum Singleton {
INSTANCE;
public static final int DEFAULT = 0;
private AtomicBoolean flag = new AtomicBoolean(false);
@Getter
private int value = DEFAULT;
public boolean plus(int value) {
return setValue(value, false);
}
public int getValue() {
return value;
}
private boolean setValue(int value, boolean rewrite) {
if (flag.compareAndSet(false, true)) {
try {
this.value = rewrite ? value : this.value + value;
} finally {
//log.info("value : [{}].", this.value);
flag.set(false);
}
return true;
}
return false;
}
public boolean reset() {
return setValue(DEFAULT, true);
}
}
我我我
我文文就算是加班也不会用枚举类型。
目录
一、枚举类型定义
枚举类型是Java 5中新增特性的一部分,它是一种特殊的数据类型,它既是一种类(class)类型却又比类类型多了些特殊的约束,但是这些约束的存在也造就了枚举类型的简洁性、安全性以及便捷性。在 Java 中它虽然算个“小”功能,却给我的开发带来了“大”方便。
二、常见用法
2.1常量
枚举是一个特殊的class,这个class相当于final static修饰,不能被继承,他的构造方法强制被私有化,下面有一个默认的构造方法private Color;所有的枚举都继承自java.lang.Enum类。由于Java 不支持多继承,所以枚举对象不能再继承其他类
public enum Color {
//每个枚举变量都是枚举类ColorEnum的实例,相当于RED=new ColorEnum(1),按序号来。
//每个成员变量都是final static修饰
RED, GREEN, BLANK, YELLOW
}
这里要注意,值一般是大写的字母,多个值之间以逗号分隔。同时我们应该知道的是枚举类型可以像类(class)类型一样,定义为一个单独的文件,也可以定义在其他类内部。
枚举表示的类型其取值是必须有限的,也就是说每个值都是可以枚举出来的
2.2switch
JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强。
enum Signal {
GREEN, YELLOW, RED
}
public class TrafficLight {
Signal color = Signal.RED;
public void change() {
switch (color) {
case RED:
color = Signal.GREEN;
break;
case YELLOW:
color = Signal.RED;
break;
case GREEN:
color = Signal.YELLOW;
break;
}
}
}
三、枚举的常见方法
Enum抽象类常见方法
Enum是Java 语言枚举类型的公共基本类,先给出总览,再依次举例分析。
返回类型 方法名(传入参数) | 方法说明 |
---|---|
int compareTo(E o) | 比较此枚举与指定对象的顺序 |
boolean equals(Object other) | 当指定对象等于此枚举常量时,返回 true。 |
Class<?> getDeclaringClass() | 返回与此枚举常量的枚举类型相对应的 Class 对象 |
String name() | 返回此枚举常量的名称,在其枚举声明中对其进行声明 |
int ordinal() | 返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零) |
String toString() | 返回枚举常量的名称,它包含在声明中 |
static<T extends Enum<T>> T static valueOf(Class<T> enumType, String name) | 返回带指定名称的指定枚举类型的枚举常量 |
3.1compareTo的使用
通过compareTo方法比较,实际上其内部是通过ordinal()值比较的
package ink.poesy.service;
/**
* @author: WenLeiWang
* Created in 2019/11/7 10:37
*/
public class EnumDemo {
public static void main(String[] args) {
Color1[] color = new Color1[]{Color1.GREEN,Color1.RED,Color1.BLACK,Color1.BLUE};
System.out.println("color[0].compareTo(color[1]):"+color[0].compareTo(color[1]));
System.out.println("color[0].compareTo(color[2]):"+color[0].compareTo(color[2]));
}
}
enum Color1{
RED,GREEN,BLUE,BLACK;
}
运行效果
3.2equals的使用
当指定对象等于此枚举常量时,返回 true。
package ink.poesy.service;
/**
* @author: WenLeiWang
* Created in 2019/11/7 10:37
*/
public class EnumDemo {
public static void main(String[] args) {
Color1[] color = new Color1[]{Color1.GREEN,Color1.RED,Color1.BLACK,Color1.BLUE};
System.out.println("color[0].equals(color[1]):"+color[0].equals(color[1]));
System.out.println("color[0].equals(color[0]):"+color[0].equals(color[0]));
}
}
enum Color1{
RED,GREEN,BLUE,BLACK;
}
运行效果
3.3getDeclaringClass的使用
返回与此枚举常量的枚举类型相对应的 Class 对象
package ink.poesy.service;
/**
* @author: WenLeiWang
* Created in 2019/11/7 10:37
*/
public class EnumDemo {
public static void main(String[] args) {
Color1[] color = new Color1[]{Color1.GREEN,Color1.RED,Color1.BLACK,Color1.BLUE};
System.out.println("color[0].getDeclaringClass():"+color[0].getDeclaringClass());
}
}
enum Color1{
RED,GREEN,BLUE,BLACK;
}
运行效果
举例有一种情况会用到这个方法
当枚举实例向上转型为Enum类型后,获取class对象引用使用getDeclaringClass()
。然后进行循环遍历枚举元素,但此时values
失效,我们需要使用getEnumConstants()
一次获取到所有枚举实例变量。
返回类型 方法名() | 方法说明 |
---|---|
T[] getEnumConstants() | 返回该枚举类型的所有元素,如果Class对象不是枚举类型,则返回null。 |
boolean isEnum() | 当且仅当该类声明为源代码中的枚举时返回 true |
package ink.poesy.service;
import com.alibaba.fastjson.JSON;
import java.util.Arrays;
/**
* @author: WenLeiWang
* Created in 2019/11/7 10:37
*/
public class EnumDemo {
public static void main(String[] args) {
//正常使用
Color1[] Color=Color1.values();
//向上转型Enum
Enum e = Color1.GREEN;
//无法调用,没有此方法
//e.values();
//获取class对象引用
Class<?> clasz = e.getDeclaringClass();
if(clasz.isEnum()) {
Color1[] col = (Color1[]) clasz.getEnumConstants();
System.out.println("color:"+ Arrays.toString(col));
}
}
}
无法调用values
运行结果
3.4name()的使用
返回此枚举常量的名称,在其枚举声明中对其进行声明
package ink.poesy.service;
/**
* @author: WenLeiWang
* Created in 2019/11/7 10:37
*/
public class EnumDemo {
public static void main(String[] args) {
Color1[] color = new Color1[]{Color1.GREEN,Color1.RED,Color1.BLACK,Color1.BLUE};
System.out.println("color[0].name():"+color[0].name());
System.out.println("color[1].name():"+color[1].name());
System.out.println("color[2].name():"+color[2].name());
}
}
enum Color1{
RED,GREEN,BLUE,BLACK;
}
3.5ordinal()的使用
package ink.poesy.service;
/**
* @author: WenLeiWang
* Created in 2019/11/7 10:37
*/
public class EnumDemo {
public static void main(String[] args) {
Color1[] color = new Color1[]{Color1.GREEN,Color1.RED};
for(int i = 0 ; i < color.length ; i++){
System.out.println("day["+i+"].ordinal():"+color[i].ordinal());
}
}
}
enum Color1{
RED,GREEN;
}
运行效果
3.6toString()的使用
返回枚举常量的名称,默认它包含在声明中。
package ink.poesy.service;
/**
* @author: WenLeiWang
* Created in 2019/11/7 10:37
*/
public class EnumDemo {
public static void main(String[] args) {
Color1[] color = new Color1[]{Color1.GREEN,Color1.RED,Color1.BLACK,Color1.BLUE};
System.out.println("color[0].toString():"+color[0].toString());
System.out.println("color[1].toString():"+color[1].toString());
System.out.println("color[2].toString():"+color[2].toString());
}
}
enum Color1{
RED,GREEN,BLUE,BLACK;
}
运行效果
就算是下面的枚举使用默认的toString也是打印名字
每一个枚举元素都是一个对象
3.7Values方法与ValueOf方法以及自定义构造方法
- 在Enum类中并没出现values()方法,但valueOf()方法还是有出现的,只不过编译器生成的valueOf()方法需传递一个name参数,而Enum自带的静态方法valueOf()则需要传递两个方法,从前面反编译后的代码可以看出,编译器生成的valueOf方法最终还是调用了Enum类的valueOf方法。
- 如果打算在enum类中定义方法,务必在声明完枚举实例后使用分号分开,倘若在枚举实例前定义任何方法,编译器都将会报错,无法编译通过,同时即使自定义了构造函数且enum的定义结束,我们也永远无法手动调用构造函数创建枚举实例
应用:
定义一些字典值可以使用枚举类型;
枚举常用的方法是values():对枚举中的常量值进行遍历;
valueof(String name) :根据名称获取枚举类中定义的常量值;
枚举类中重写了toString()方法,返回的是枚举常量的名称;
package ink.poesy.service;
import com.alibaba.fastjson.JSON;
/**
* @author: WenLeiWang
* Created in 2019/11/7 10:37
*/
public class EnumDemo {
public static void main(String[] args) {
Color1[] color1 = Color1.values();
String color2 = Color1.valueOf("RED").getName();
System.out.println("color.values():"+ JSON.toJSONString(color1));
System.out.println("color.valueOf():"+ color2);
System.out.println("春梅红对应RGB:"+Color1.getColor("春梅红"));
}
}
enum Color1{
/**
* 红色
*/
RED("春梅红","241,147,156"),
/**
* 绿色
*/
GREEN("孔雀绿","34,148,83");
/**
* 自定义构造方法
* 私有构造,防止被外部调用
* @param name 颜色名
* @param rgb 颜色rgb
*/
private Color1(String name,String rgb){
this.name = name;
this.rgb = rgb;
}
/**
* 自定义函数:通过颜色名称获取颜色rgb,values的应用
* 遍历方法有两种
* 1.values
* 2.上面说的getEnumConstants()
* @param name 颜色名称
* @return 颜色rgb
*/
public static String getColor(String name){
//遍历枚举元素
for(Color1 color : Color1.values()){
if(color.getName().equals(name)){
return color.getRgb();
}
}
return null;
}
private String name;
private String rgb;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRgb() {
return rgb;
}
public void setRgb(String rgb) {
this.rgb = rgb;
}
}
运行效果
四、覆盖枚举的方法
enum类跟常规类的定义没什么区别,因此也能覆盖父类方法,父类Enum中的定义的方法只有toString方法没有使用final修饰,因此只能覆盖toString方法
public enum Color {
RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
// 成员变量
private String name;
private int index;
// 构造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
//覆盖方法
@Override
public String toString() {
return this.index+"_"+this.name;
}
}
五、定义抽象方法
package ink.poesy.service;
import com.alibaba.fastjson.JSON;
import java.util.Arrays;
/**
* @author: WenLeiWang
* Created in 2019/11/7 10:37
*/
public class EnumDemo {
public static void main(String[] args) {
System.out.println("Color1.GREEN.getName():"+Color1.GREEN.getName());
}
}
enum Color1{
/**
* 红色
*/
RED{
//实现抽象方法
@Override
public String getName() {
return "红色";
}
},
/**
* 绿色
*/
GREEN{
//实现抽象方法
@Override
public String getName() {
return "绿色";
}
};
//抽象方法
public abstract String getName();
}
运行效果
六、使用接口
由于Java单继承的原因,enum类并不能再继承其它类,但并不妨碍它实现接口,因此enum类同样是可以实现多接口的
6.1继承接口
public interface Behaviour {
void print();
String getInfo();
}
public enum Color implements Behaviour{
RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
// 成员变量
private String name;
private int index;
// 构造方法
private Color(String name, int index) {
this.name = name;
this.index = index;
}
//接口方法
@Override
public String getInfo() {
return this.name;
}
//接口方法
@Override
public void print() {
System.out.println(this.index+":"+this.name);
}
}
6.2使用接口组织枚举
public interface Food {
enum Coffee implements Food{
BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO
}
enum Dessert implements Food{
FRUIT, CAKE, GELATO
}
}
package ink.poesy.service;
import com.alibaba.fastjson.JSON;
import java.util.Arrays;
/**
* 测试继承接口的枚举的使用
* @author: WenLeiWang
* Created in 2019/11/7 10:37
*/
public class EnumDemo {
public static void main(String[] args) {
System.out.println("Coffee:");
for (Food.Coffee dessertEnum : Food.Coffee.values()) {
System.out.print(dessertEnum + " ");
}
System.out.println("\nDessert:");
for (Food.Dessert dessertEnum : Food.Dessert.values()) {
System.out.print(dessertEnum + " ");
}
System.out.println("\nFood.Dessert.CAKE值为:"+Food.Dessert.CAKE);
}
}
运行效果
七、枚举单例
什么是单例模式和实现方式查看文章:软件设计模式之单例模式
package ink.poesy.service;
import com.alibaba.fastjson.JSON;
import java.util.Arrays;
/**
* 枚举单例实现
* @author: WenLeiWang
* Created in 2019/11/7 10:37
*/
public enum EnumDemo {
INSTANCE;
private String name;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
}
像常规类一样编写enum类,为其添加变量和方法,访问方式也更简单,使用SingletonEnum.INSTANCE
进行访问,更重要的是使用枚举单例的写法,我们完全不用考虑序列化和反射的问题。
回归
那么,通过上面我们又回到开始的代码,就能得到解释了
enum Singleton {
/**
* 枚举单例,调用标记
*/
INSTANCE;
public static final int DEFAULT = 0;
/**
* 百度了下这个是原子变量,保证一致性
*/
private AtomicBoolean flag = new AtomicBoolean(false);
/**
* lombok的get方法
*/
@Getter
private int value = DEFAULT;
/**
* 调用方法
* @param value 值
* @return 布尔
*/
public boolean plus(int value) {
return setValue(value, false);
}
/**
* 获取值
* @return 值
*/
public int getValue() {
return value;
}
private boolean setValue(int value, boolean rewrite) {
//乐观锁
if (flag.compareAndSet(false, true)) {
try {
//三目运算符:判断赋不变还是叠加
this.value = rewrite ? value : this.value + value;
} finally {
//都执行此
flag.set(false);
}
return true;
}
return false;
}
public boolean reset() {
return setValue(DEFAULT, true);
}
}
枚举真好用。
等待扩展未完待续。。。
关于枚举集合的使用
EnumSet用法
本文为学习笔记来源整理自网络,如有侵犯留言联系。
以上内容如有争议、指正,留言给我~