224 - 枚举

1、引入

【1】数学:枚举法:

1<x<4

2<y<5

求x+y=6

枚举法:一枚一枚的列举出来。前提:有限,确定

【2】在java中,类的对象是有限个,确定的。这个类我们可以定义为枚举类。

举例:

星期:一二三四五六日  

性别:男女

季节:春夏秋冬

【3】自定义枚举类:(JDK1.5之前自定义枚举类) 

代码示例:
Season类:

package test5_Enum;

/**
 * @Auther: zhoulz
 * @Description: 定义枚举类:季节
 * @version: 1.0
 */
public class Season {
    //属性
    //private final String seasonName = "春天";//季节名字
    //private final String seasonDesc = "出暖花开";//季节描述
    //季节都是确定的,可以说是常量,因此要赋值
    //但是赋值后,就无法更改了,即不能向上面那么写,
    // 怎么办:利用构造器

    private final String seasonName;//季节名字
    private final String seasonDesc;//季节描述
    //利用构造器对属性进行赋值操作:
    //构造器私有化,外界不能调用这个构造器,只能Season内部自己调用
    Season(String seasonName,String seasonDesc){
        this.seasonName = seasonName;
        this.seasonDesc = seasonDesc;
    }

    //提供枚举类的有限的、确定的对象:
    //Season spring = new Season("春天","春暖花开");
    //改为:
    //public static - 为了外界能调用,且Season. 直接调用;final - 外界不能该;SPRING - 常量的话,就大写。
    public static final Season SPRING = new Season("春天","春暖花开");

    public static final Season SUMMER = new Season("夏天","烈日炎炎");
    public static final Season AUTUMN = new Season("秋天","硕果累累");
    public static final Season WINTER = new Season("冬天","冰天雪地");

    //上面基本创建好了枚举类
    //额外因素:
    //因为都是常量,且值都设置好了,所以不用set()方法了
    //但可以有get()方法
    public String getSeasonName() {
        return seasonName;
    }

    public String getSeasonDesc() {
        return seasonDesc;
    }

    //还可以有toString()方法
    @Override
    public String toString() {
        return "Season{" +
                "seasonName='" + seasonName + '\'' +
                ", seasonDesc='" + seasonDesc + '\'' +
                '}';
    }
}

测试类:Test1

package test5_Enum;

/**
 * @Auther: zhoulz
 * @Description: test5_Enum
 * @version: 1.0
 */
public class Test1 {
    public static void main(String[] args) {
        Season summer = Season.SUMMER;
        System.out.println(summer/*.toString()*/);
        //相当于:
        System.out.println(summer.toString());

        System.out.println(summer.getSeasonName());
    }
}

2、JDK1.5之后使用enum关键字来创建枚举类

较之前自定义的枚举类:

 变为下面的枚举类:

代码示例:

package test6_Enum_2;

/**
 * @Auther: zhoulz
 * @Description: 定义枚举类:季节
 * @version: 1.0
 */
public enum Season {

    //提供枚举类的有限的、确定的对象:—— enum枚举类要求对象(常量)必须放在最开始位置
    //然后,改成:
    //多个对象之间用,进行连接,最后一个对象后面用;结束

    SPRING ("春天","春暖花开"),
    SUMMER ("夏天","烈日炎炎"),
    AUTUMN ("秋天","硕果累累"),
    WINTER ("冬天","冰天雪地");

    //属性
    private final String seasonName;//季节名字
    private final String seasonDesc;//季节描述
    //利用构造器对属性进行赋值操作:
    //构造器私有化,外界不能调用这个构造器,只能Season内部自己调用
    Season(String seasonName, String seasonDesc){
        this.seasonName = seasonName;
        this.seasonDesc = seasonDesc;
    }

    //上面基本创建好了枚举类
    //额外因素:
    //因为都是常量,且值都设置好了,所以不用set()方法了
    //但可以有get()方法
    public String getSeasonName() {
        return seasonName;
    }

    public String getSeasonDesc() {
        return seasonDesc;
    }

    //还可以有toString()方法
    @Override
    public String toString() {
        return "Season{" +
                "seasonName='" + seasonName + '\'' +
                ", seasonDesc='" + seasonDesc + '\'' +
                '}';
    }
}

同样,定义好了枚举类,我们就可以使用了。

使用枚举类:

代码示例:

package test6_Enum_2;

/**
 * @Auther: zhoulz
 * @Description: test6_Enum_2
 * @version: 1.0
 */
public class TestSeason {
    public static void main(String[] args) {
        Season winter = Season.WINTER;
        System.out.println(winter);
        //将重写后的toString()方法注释后,得到输出后的 winter为  WINTER
        //而在之前自定义的枚举中,如果将重写后的toString()方法注释,
        //得到的结果为:test5_Enum.Season@14ae5a5

        //而结果WINTER 说明打印的不是一个地址,从而说明enum定义的Season不是继承自Object
        //获取其父类:
        System.out.println(Season.class.getSuperclass().getName());//结果:java.lang.Enum

        //enum关键字对应的枚举类的上层父类是 :java.lang.Enum
        //但是我们自定义的枚举类的上层父类:Object
    }
}

在源码中经常看到别人定义的枚举类形态:

public enum Season {
    SPRING,
    SUMMER,
    AUTUMN,
    WINTER;
}

        为什么这么简单:因为这个枚举类底层没有属性,属性,构造器,toString,get方法都删掉不写了,然后案例来说应该写为:SPRING() ,  现在连()都可以省略了, 就变成  SPRING。

看到的形态就剩:常量名(对象名)

举例:

Thread中的枚举类:State

代码示例:

public enum State {
        /**
         * Thread state for a thread which has not yet started.
         */
        NEW,

        /**
         * Thread state for a runnable thread.  A thread in the runnable
         * state is executing in the Java virtual machine but it may
         * be waiting for other resources from the operating system
         * such as processor.
         */
        RUNNABLE,

        /**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */
        BLOCKED,

        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
         * that object. A thread that has called <tt>Thread.join()</tt>
         * is waiting for a specified thread to terminate.
         */
        WAITING,

        /**
         * Thread state for a waiting thread with a specified waiting time.
         * A thread is in the timed waiting state due to calling one of
         * the following methods with a specified positive waiting time:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
        TIMED_WAITING,

        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        TERMINATED;
    }

3、Enum类的常用方法

代码示例:

Season枚举:

public enum Season {
    SPRING,
    SUMMER,
    AUTUMN,
    WINTER;
}

测试类: 

package test7_Enum_3;

/**
 * @Auther: zhoulz
 * @Description: test7_Enum_3
 * @version: 1.0
 */
public class TestSeason {
    public static void main(String[] args) {
        //用enum关键字创建的Season枚举类上面的父类是:java.lang.Enum,
        //其下的常用方法,子类Season可以直接拿过来使用:

        //1、toString() —— 获取对象的名字
        Season autumn = Season.AUTUMN;
        System.out.println(autumn/*.toString()*/); //AUTUMN

        System.out.println("----------");
        //2、values() —— 返回枚举类对象的数组
        //values()是静态的,所以直接Season. 去调
        Season[] values = Season.values();
        //使用增强for循环,对values进行遍历
        //对values进行遍历,然后用Season s 去接收
        for (Season s:values){
            System.out.println(s.toString());
        }

        System.out.println("----------");
        //3、valueOf() —— 通过对象名字获取这个枚举对象
        //注意:对象的名字必须传正确,否则抛出异常

        //注意:valueOf()方法 要求传入的是一个String name (字符串对象) ,
        // 然后返回的是一个Season对象
        Season autumn1 = Season.valueOf("AUTUMN");
        System.out.println(autumn1);
    }
}

4、枚举类实现接口

(1)首先,定义一个接口:

代码示例:

package test8_Enum_4_implement_interface;

/**
 * @Auther: zhoulz
 * @Description: test8_Enum_4_implement_interface
 * @version: 1.0
 */
public interface TestInterface {
    void show();
    // 接口体中只进行方法的声明,不允许提供方法的实现,
    // 方法的定义没有方法体,且用分号结尾
}

(2)然后,创建一个枚举类实现接口,并且重写show方法:

代码示例:

package test8_Enum_4_implement_interface;

/**
 * @Auther: zhoulz
 * @Description: test8_Enum_4_implement_interface
 * @version: 1.0
 */
public enum Season implements TestInterface{
    SPRING,
    SUMMER,
    AUTUMN,
    WINTER;

    //实现接口,必须要对里面的抽象方法进行重写:
    @Override
    public void show(){
        System.out.println("这是Season!!!");
    }
}

(3)最后,创建测试类:

代码示例:

package test8_Enum_4_implement_interface;

/**
 * @Auther: zhoulz
 * @Description: test8_Enum_4_implement_interface
 * @version: 1.0
 */
public class Test1 {
    public static void main(String[] args) {
        Season autumn = Season.AUTUMN;
        autumn.show();

        //同理
        Season summer = Season.SUMMER;
        summer.show();
    }
}

结果发现:
        所有创建的枚举对象,调用这个show方法的时候,走的都是同一个方法,结果都一样

但是现在要求:

                不同的对象  调用的show方法也不同。

代码示例:

测试类:同上

枚举类:

package test8_Enum_4_implement_interface;

/**
 * @Auther: zhoulz
 * @Description: test8_Enum_4_implement_interface
 * @version: 1.0
 */
public enum Season implements TestInterface{
    SPRING{
        @Override
        public void show() {
            System.out.println("这是春天!!!!");
        }
    },
    SUMMER{
        @Override
        public void show() {
            System.out.println("这是夏天!!!");
        }
    },
    AUTUMN{
        @Override
        public void show() {
            System.out.println("这是秋天!!");
        }
    },
    WINTER{
        @Override
        public void show() {
            System.out.println("这是冬天!");
        }
    };

    //实现接口,必须要对里面的抽象方法进行重写:
    /*@Override
    public void show(){
        System.out.println("这是Season!!!");
    }*/
}

结果:

5、实际应用

代码示例:

Person类:

package test9_Enum_5_practical_application;

/**
 * @Auther: zhoulz
 * @Description: test9_Enum_5_practical_application
 * @version: 1.0
 */
public class Person {
    //属性
    private int age;
    private String name;
    //private String sex;
    //不用属性sex:
    private Gender sex;

    //set、get方法:
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    /*public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        if (sex == "男" || sex == "女"){ //更好?:if (sex.equals("男") || sex.equals("女"))
            this.sex = sex;
        }
        else{
            this.sex = "性别设置无效!";
            System.out.println("请您重新设置性别!!!");
        }
    }*/
    //
    //提供对应的枚举类的对象的set、get方法
    public Gender getSex() {
        return sex;
    }

    public void setSex(Gender sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                '}'; //记住把sex注释掉,创建了Gender sex后就会报错了
    }
}

枚举类:

package test9_Enum_5_practical_application;

/**
 * @Auther: zhoulz
 * @Description: test9_Enum_5_practical_application
 * @version: 1.0
 */
public enum Gender {
    男,
    女;
}

测试类:

package test9_Enum_5_practical_application;

/**
 * @Auther: zhoulz
 * @Description: test9_Enum_5_practical_application
 * @version: 1.0
 */
public class Test {
    public static void main(String[] args) {
        Person p = new Person();
        p.setAge(20);
        p.setName("小丽");
        //p.setSex("女");

        //p.setSex("qwewdwdfasf"); //不是自己想要的,但也不会报错
        //以前的做法是在setSex()方法中进行判断,
        //现在通过枚举来解决 : 创建一个枚举类,把属性sex及其方法去掉,
        //当创建了枚举类对象Gender sex后,设置的不是“男、女”就会报错了。
        //而且,不能直接传入“男、女”
        //应该是:
        p.setSex(Gender.男);//会提示传入:Gender sex 对象
                            //输入Gender. 后,自动获取
        //即:传入枚举类Gender的对象:-->在入口处对参数进行了限制

        System.out.println(p);
    }
}

还可以通过枚举结合switch处理:

代码示例:

package test9_Enum_5_practical_application;

/**
 * @Auther: zhoulz
 * @Description: test9_Enum_5_practical_application
 * @version: 1.0
 */
public class Test2 {
    public static void main(String[] args) {
        Gender sex = Gender.男;

        //switch后面的()中可以传入枚举类型
        //switch后面的():int,short,byte,char,String ,枚举
        // long、float、double不行
        switch (sex){
            case 女:
                System.out.println("一个女孩。");
                break;
            case 男:
                System.out.println("一个男孩。");
                break;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值