JavaSE——面向对象高级三(3/5)-枚举(认识枚举、拓展:抽象枚举、用枚举实现单例模式、枚举的应用场景)

简介: JavaSE——面向对象高级三(3/5)-枚举(认识枚举、拓展:抽象枚举、用枚举实现单例模式、枚举的应用场景)

枚举的概述

认识枚举

  • 枚举是一种特殊类。

枚举类的格式

修饰符 enum 枚举类名{

       名称1,名称2,...;

       其他成员...

}

public enum A{
    X,Y,Z;
    ...
}

注意

  • 枚举类中的第一行,只能写一些合法的标识符(名称),多个名称用逗号隔开。
  • 这些名称,本质是常量,每个常量都会记住枚举类的一个对象

枚举类的特点

public enum A{
    X,Y,Z;
}

实际上完整代码为:

Complied from "A.java"
public final class A extends java.lang.Enum<A>{
    public static final A X = new A();
    public static final A Y = new A();
    public static final A Z = new A();
}

具有以下特点:

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

第一点:枚举类的第一行都是常量,记住的是枚举类的对象


A a = A.Y;

因为枚举类的第一行都是常量,记住的是枚举类的对象,所以我们可以直接用枚举类得到里面的象,例如:枚举类名称.枚举类常量1、枚举类名称.枚举类常量2;A.X、A.Y。

第二点:枚举类的构造器是私有的,不能对外创建对象。

public class Test{
    public static void main(String[] args){
        A a = new A(); //会报错
        //枚举类不能对外创建对象
    }
}

第三点:枚举类提供了一些额外的API

A[] a1 = A.values(); //拿到全部对象
A a2 = A.valueOf("Z"); //拿到其中一个对象
System.out.println(a2.name()); //输出结果为Z对象的name
System.out.println(a2.ordinal()); //索引

都是为枚举类新增的一些API。

拓展:抽象枚举

抽象枚举简单来说,就是枚举类里面定义了抽象方法的枚举类。

抽象枚举在创建自身的对象时,必须要重写方法,所以直接在第一行中进行方法重写:

public enum B{
    X(){
        @Override
        public void go(){
        }
    },Y(){
        @Override
        public void go(){
        }
    };
    
    private String name; //第一行之后就可以正常写变量了
    
    public abstract void go(); //抽象方法
    
    public String getName(){
        return name;
    }
    public String setName(name){
        this.name = name;
    }
}

写构造器时,可以不用写修饰符,默认为private。

public enum B{
    X(){
        @Override
        public void go(){
        }
    },Y(){
        @Override
        public void go(){
        }
    };
    
    /* private */ B(){
    }
    /* private */ B(String name){
        this.name;
    }
 
    private String name; 
    
    public abstract void go(); //抽象方法
    
    public String getName(){
        return name;
    }
    public String setName(name){
        this.name = name;
    }
}

如果把无参构造器去掉,就会报错,因为前面枚举类创建的对象重写方法时要调用到无参构造器。

当然,也可以调用有参构造器

public enum B{
    X(){
        @Override
        public void go(){
        }
    },Y("张三"){
        @Override
        public void go(){
            System.out.println(getName() + "在跑~");
        }
    };
    
    B(){
    }
    B(String name){
        this.name;
    }
 
    private String name; 
    
    public abstract void go(); //抽象方法
    
    public String getName(){
        return name;
    }
    public String setName(name){
        this.name = name;
    }
}
public class Test{
    public static void main(String[] args){
        B y = B.Y;
        y.go();
    }
}

运行结果为:

张三在跑~

这个过程是:Y对象在用B枚举类创建自己这个对象,调用B的有参构造器,传入参数“张三”,存储在name变量中;且因为是抽象枚举,创建Y对象时需要重写其所有抽象方法,重写go方法时取到name变量的值“张三”并输出。

用枚举实现单例模式

使用枚举是可以直接实现单例模式的,


复习一下单例设计模式:

       一个类可以new出很多对象,但对于某个应用场景下,我们希望这个类只能有一个对象这就是单例设计模式所解决的问题。也就是说,单例设计模式是确保一个类只有一个对象,我们学过饿汉式单例和懒汉式单例,前者是先把对象创建好,后者则在使用该设计模式时再进行创建。

       写法:


  • 把类的构造器私有。
  • 定义一个类变量记住类的一个对象。·
  • 定义一个类方法,返回对象。

用枚举类的方式实现单例:

public enum C{
    X; //单例
}

枚举的应用场景

  • 用来表示一组信息,然后作为参数进行传输。

(可以类比C语言的枚举类型变量)

如果选择定义一个一个的常量来表示一组信息,并作为参数传输,那么其参数值不受约束

而选择定义枚举表示一组信息,并作为参数传输,代码可读性好,参数值得到了约束,对使用者更友好

例如:

public class Constant{
    public static final int BOY = 0;
    public static final int GIRL = 1;
}
 
public class Test{
    public static void main(String[] args){
        //check(1);
        //check(21);  //传入参数不受约束
        check(Constant.BOY);
    }
    public static void check(int sex){
        switch(sez){
            case Constant.BOY:
                ...
                break;
            case Constant.GIRL:
                ...
                break;
        }
    }
}

如果用常量做信息标志和分类,就存在传入参数不受约束的问题。

所以就开始用枚举了:

public enum Constant2{
    BOY,GIRL;  //定义枚举类型
}
 
public class Test{
    public static void main(String[] args){
        //check(1);
        //check(21);  //传入参数不受约束
        check(Constant2.BOY);
    }
    public static void check(Constant2 sex){
        switch(sez){
            case BOY: //Constant.BOY前缀可以省略
                ...
                break;
            case GIRL:
                ...
                break;
        }
    }
}

虽然枚举做信息标志和分类比较好,但是在实际中可能会发现还是很多人用常量,主要是因为常量用起来比较简单,其他原因就是常量也有一些优势,比如可以定义不同类型的常量,使用起来比较灵活。

所以两种方式都会使用到,并没有相互淘汰掉谁。


END



目录
相关文章
|
6月前
|
Java Spring
使用枚举定义常量更好点儿
使用枚举定义常量更好点儿
|
6月前
|
C语言
|
6月前
|
开发框架 Java 编译器
Java反射,枚举讲解
Java反射,枚举讲解
74 0
|
6月前
|
安全 算法 编译器
【C++基础语法 枚举】C/C++ 中enum枚举量的介绍:介绍enum枚举量在C/C中的作用和使用方法
【C++基础语法 枚举】C/C++ 中enum枚举量的介绍:介绍enum枚举量在C/C中的作用和使用方法
77 2
|
6月前
|
安全 API C#
C#.Net筑基-类型系统②常见类型--枚举Enum
枚举(enum)是C#中的一种值类型,用于创建一组命名的整数常量。它们基于整数类型(如int、byte等),默认为int。枚举成员可指定值,未指定则从0开始自动递增。默认值为0。枚举可以与整数类型互相转换,并可通过`[Flags]`特性表示位域,支持位操作,用于多选场景。`System.Enum`类提供了如`HasFlag`、`GetName`等方法进行枚举操作。
|
5月前
详细解读COM中集合和枚举器笔记(2)枚举器内部实现
详细解读COM中集合和枚举器笔记(2)枚举器内部实现
21 0
|
6月前
|
存储 C# 索引
C#学习相关系列之数据类型类的定义(一)
C#学习相关系列之数据类型类的定义(一)
116 0
|
6月前
|
存储 安全 Java
【Java 枚举】详细介绍枚举的作用以及适用范围
【Java 枚举】详细介绍枚举的作用以及适用范围
104 0
|
存储 C++
【C++11保姆级教程】强类型枚举(强类型枚举)和constexpr
【C++11保姆级教程】强类型枚举(强类型枚举)和constexpr
196 0
|
Java 编译器 数据库
Java维护常量方式的比较——接口、常量类与枚举
Java维护常量方式的比较——接口、常量类与枚举 一、示例 ​ 1.让类实现定义了常量的接口