原来你是这样的java枚举类型(enum)

在此之前我一直以为枚举类型是这样

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;
}

运行效果
CompareTo运行效果

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;
}

运行效果
equals运行效果

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;
}

运行效果
getDeclaringClass运行效果

举例有一种情况会用到这个方法

当枚举实例向上转型为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
无法调用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;
}

运行效果
ordinal运行效果

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运行效果
就算是下面的枚举使用默认的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;
    }
}

运行效果
value运行效果

四、覆盖枚举的方法

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用法


本文为学习笔记来源整理自网络,如有侵犯留言联系。
以上内容如有争议、指正,留言给我~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

园长的牧歌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值