面向对象高级三-03.认识枚举,枚举的作用和应用场景

一.枚举

package com.njau.d5_enum;

/**
 * 枚举类的第一行只能罗列一些名称,这些名称都是常量,并且每个常量记住的都是枚举类的一个对象
 * 枚举类的构造器都是私有的(写不写都是私有的),因此枚举类不能对外创建对象
 * 枚举都是最终类,不可以被继承(可以在A.class的反编译中看到final修饰)
 * 枚举类中,从第二行开始,可以定义类的其他各种成员
 * 编译器为枚举类新增了几个方法,并且枚举类都是继承:java.lang.Enum类的,从enum类也会继承到一些方法
 */
public enum A {
    X,Y,Z;

    private String name;

    A(){
    }

    A(String name){
        this.name = name;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

 枚举类的第一行只能罗列一些名称,这些名称都是常量,并且每个常量记住的都是枚举类的一个对象。枚举类中,从第二行开始,可以定义类的其他各种成员(构造器,get/set方法)。

package com.njau.d5_enum;

/**
 * 认识枚举
 * 枚举类的对象
 */
public class Test {
    public static void main(String[] args) {
        A a1 = A.X;
        System.out.println(a1);  // X
//        A a = new A();  枚举类的构造器是私有的,不能对外创建对象
        // 2、枚举类的第一行都是常量(public static final修饰),因此可以使用A.常量名进行直接调用
        A a2 = A.Y;
        // 3、枚举类提供了一些额外的API供我们使用
        A[] as = A.values();  // 拿到枚举类的全部对象装入as数组中
        A a3 = A.valueOf("Z");
        System.out.println(a3.name());  // Z
        System.out.println(a3.ordinal());  // 返回a3(Z)在对象数组中的索引
    }
}

在Test类中,我们可以访问A中X枚举对象,并将该对象交给A类型的一个变量a1记录。编译过后我们可以反编译一下看A.class文件是什么样子。

使用javap命令在cmd反编译:

public final class com.njau.d5_enum.A extends java.lang.Enum<com.njau.d5_enum.A> {
  public static final com.njau.d5_enum.A X;
  public static final com.njau.d5_enum.A Y;
  public static final com.njau.d5_enum.A Z;
  public static com.njau.d5_enum.A[] values();
  public static com.njau.d5_enum.A valueOf(java.lang.String);
  public java.lang.String getName();
  public void setName(java.lang.String);
  static {};
}

使用idea反编译:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.njau.d5_enum;

public enum A {
    X,
    Y,
    Z;

    private String name;

    private A() {
    }

    private A(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

反编译后我们可以看到,其中的枚举对象实际上都是枚举类A中所定义的常量。且该枚举类被final修饰,即枚举类都是最终类,不可以被继承。枚举类的构造器都是私有的(写不写都是私有的),因此枚举类不能对外创建对象。

枚举类为我们新增了很多方法,如values()方法是拿到当前枚举类的所有枚举对象,并封装在类型数组中。valueOf是根据当前的枚举对象名,如‘X’,‘Y’,‘Z’,直接拿到对应的枚举对象。

package com.njau.d5_enum;

/**
 * 认识枚举
 * 枚举类的对象
 */
public class Test {
    public static void main(String[] args) {
        A a1 = A.X;
        System.out.println(a1);  // X
//        A a = new A();  枚举类的构造器是私有的,不能对外创建对象
        // 2、枚举类的第一行都是常量(public static final修饰),因此可以使用A.常量名进行直接调用
        A a2 = A.Y;
        // 3、枚举类提供了一些额外的API供我们使用
        A[] as = A.values();  // 拿到枚举类的全部对象装入as数组中
        A a3 = A.valueOf("Z");
        System.out.println(a3.name());  // Z
        System.out.println(a3.ordinal());  // 返回a3(Z)在对象数组中的索引
    }
}

二.抽象枚举

所谓抽象枚举,就是在枚举类中定义抽象方法。这样当我们在枚举类中声明一个枚举的时候,就不能仅声明一个枚举对象了,而是要在枚举对象中重写该抽象方法,这就和匿名内部类很像。

package com.njau.d5_enum;


/**
 * 抽象枚举:所谓抽象枚举,即在枚举中定义了抽象方法
 * 因为抽象枚举中含有抽象方法,必须重写抽象方法后才能创建实例对象,否则无法创建实例对象,因此在定义对象时要重写抽象方法,才可以定义对象
 */
public enum B {
    // 重写抽象方法,才能定义对象
    X("张三") {
        @Override
        public void go() {
            System.out.println(getName() + "跑了··");
        }
    },Y("李四") {
        @Override
        public void go() {
            System.out.println(getName() + "跑了··");
        }
    };
    private String name;

    B(){}


    B(String name){
        this.name = name;
    }

    public void setName(String name){
        this.name = name;
    }

    public String getName(){
        return name;
    }

    public abstract void go();
}

定义一个抽象方法go,在定义枚举对象时要调用其无参构造器"()",并对抽象方法进行重写。定义有参无参构造器,只能是私有,默认也是私有,因为枚举类构造器必须私有。定义一个属于name和其get/set方法。这样在定义枚举对象时也可以调用其有参构造器并传入参数。

package com.njau.d5_enum;

/**
 * 认识枚举
 * 枚举类的对象
 */
public class Test {
    public static void main(String[] args) {
        A a1 = A.X;
        System.out.println(a1);  // X
//        A a = new A();  枚举类的构造器是私有的,不能对外创建对象
        // 2、枚举类的第一行都是常量(public static final修饰),因此可以使用A.常量名进行直接调用
        A a2 = A.Y;
        // 3、枚举类提供了一些额外的API供我们使用
        A[] as = A.values();  // 拿到枚举类的全部对象装入as数组中
        A a3 = A.valueOf("Z");
        System.out.println(a3.name());  // Z
        System.out.println(a3.ordinal());  // 返回a3(Z)在对象数组中的索引

        System.out.println("-------------------------------------------");
        B b1 = B.X;
        b1.go();   // 张三跑了··
        B b2 = B.Y;
        b2.go();   // 李四跑了··
    }
}

三.枚举的作用

使用枚举的作用就是创建单例(一个类只能创建一个实现类对象,就是单例)。

单例

package com.njau.d5_enum;
// 利用枚举实现单例设计模式
public enum C {
    X;  // 单例
}

四.枚举的应用场景

枚举最常见的应用场景是用来做信息分类,比如我们要男生去男厕,女生去女厕,要对男女进行信息分类。

如果我们不使用枚举,只是使用0/1这种软编码来代表男/女。那么我可以随意填入2,3等数字。

package com.njau.d6_enum2;

/**
 * 枚举的常见应用场景:用来表示一组信息,然后作为参数进行传输
 */
public class Test {
    public static void main(String[] args) {
        // 目标:掌握枚举的应用场景,做信息标志和分类
        check(1);


    }
    public static void check(int sex){
        switch (sex){
            case 0:
                System.out.println("去男厕所");
                break;
            case 1:
                System.out.println("去女厕所");
                break;
        }
    }
}

而且可读性很不好,为了更好的可读性,我们可以使用常量。定义一个常量类:Constant.java

package com.njau.d6_enum2;

public class Constant {
    public static final int BOY = 1;
    public static final int GIRL = 2;
}

通过常量去匹配,可读性更好。 但是仍然可以乱写,比如写21,但是无法匹配。常量入参不受约束。

package com.njau.d6_enum2;

/**
 * 枚举的常见应用场景:用来表示一组信息,然后作为参数进行传输
 */
public class Test {
    public static void main(String[] args) {
        // 目标:掌握枚举的应用场景,做信息标志和分类
//        check(1);
        check(Constant.BOY);     使用常量,软编码->硬编码
//        check(12);  乱输也会有结果,不允许,因此要使用枚举

    }
    
    public static void check(int sex){
        switch (sex){
            case Constant.BOY:
                System.out.println("去男厕所");
                break;
            case Constant.GIRL:
                System.out.println("去女厕所");
                break;
        }
    }
}

我们还可以使用枚举:

定义一个枚举类:Constant2.java

package com.njau.d6_enum2;

public enum Constant2 {
    BOY,GIRL
}

使用该枚举类进行信息分类,那么会受到严格的约束,不能乱写。

package com.njau.d6_enum2;

/**
 * 枚举的常见应用场景:用来表示一组信息,然后作为参数进行传输
 */
public class Test {
    public static void main(String[] args) {
        // 目标:掌握枚举的应用场景,做信息标志和分类
//        check(1);
//        check(Constant.BOY);     使用常量,软编码->硬编码
//        check(12);  乱输也会有结果,不允许,因此要使用枚举
        check(Constant2.BOY);

    }
    public static void check(Constant2 sex){
        switch (sex){
            case BOY:      // Constant2.BOY会报错,因为不需要Constant
                System.out.println("去男厕所");
                break;
            case GIRL:
                System.out.println("去女厕所");
                break;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值