JAVA和Nginx 教程大全

网站首页 > 精选教程 正文

Java路径-29-Java枚举 java源程序文件的扩展名为

wys521 2024-10-31 16:20:27 精选教程 28 ℃ 0 评论

1 枚举的概念

枚举:列举,一个一个地列出来。 Java枚举:把某个类型的对象,全部列出来。

  • 什么情况下会用到枚举类型?

某些类的对象只有确定的有限个时,可以把这样的类声明为枚举。

例如:

星期:Monday(星期一)......Sunday(星期天)

性别:Male(男)、Female(女)

月份:January(1月)......December(12月)

季节:Spring(春天)......Winter(冬天)

  • 枚举是一种特殊的类,特殊在它的对象是有限的几个常量对象。它既是一种类(class)类型却又比类类型多了些特殊的约束,枚举的本质是一种受限制的类。

当需要定义一组常量时,可以使用枚举。

2 枚举的定义

枚举是JDK1.5新增的引用数据类型。

  • 枚举的对象的属性不应允许被改动,所以应该使用 private final 修饰
  • 属性应该在构造器中为其赋值
  • 若枚举显式的定义了带参数的构造器,则在列出枚举值时也必须对应地传入参数
  • 枚举的实现:
    • jdk1.5之前,自定义枚举类
    • jdk1.5,可以使用 enum 关键字定义枚举

2.1 自定义枚举类

  • 要求:
    • 私有化类的构造器,保证不能在类的外部创建其对象
    • 在类的内部创建枚举类的实例,并用声明为 public static final 的变量来引用
    • 对象如果有实例变量,应该声明为private final,并在构造器中初始化
class Season {
    //声明Season对象的属性:使用 private final 修饰
    private final String seasonName;
    private final String seasonDesc;

    //私有化Season类的构造器,并给对象属性赋值
    private Season(String seasonName, String seasonDesc) {
        this.seasonName = seasonName;
        this.seasonDesc = seasonDesc;
    }

    //在类的内部创建当前枚举类的对象,变量用 public static final 修饰
    //public:外部可以使用枚举类的实例
    //static:外部可以使用“类名.对象名”调用
    //final:修饰的变量只能指向一个对象,保存的地址值不能更改
    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("冬天", "白雪皑皑");

    //其他需求
    //获取枚举类的对象的属性
    public String getSeasonName() {
        return seasonName;
    }

    public String getSeasonDesc() {
        return seasonDesc;
    }
    
    //提供toString()
    @Override
    public String toString() {
        return "Season{" +
                "seasonName='" + seasonName + '\'' +
                ", seasonDesc='" + seasonDesc + '\'' +
                '}';
    }
}

public class SeasonTest {
    public static void main(String[] args) {
        Season spring = Season.SPRING;
        System.out.println(spring.getSeasonName());
        System.out.println(spring);
    }
}

2.2 使用enum定义枚举

jdk1.5之前,枚举的定义格式太繁琐,存在很多重复代码 使用 enum 关键字简化枚举的定义

  • 声明格式:
  • [修饰符] enmu 枚举名{
    //实例列表
    //其他成员列表
    }

枚举的所有实例必须在其他成员的前面显式列出(多个实例之间 , 分隔 ; 结尾,只存在实例列表时,最后一个实例后面的 ; 可省略,存在其他成员时,不能省略),它们实际上都是 public static final 修饰的常量对象,不用自己添加修饰符,填上反而会报错。

枚举的所有构造器只能使用 private 访问控制符,并且是隐式私有的。

switch 表达式的case 子句可以直接使用 Enum定义的枚举的对象的名字。

如果枚举中只有一个对象,则可以作为单例模式的一种实现方式。

//RED、GREEN、BLUE不是枚举Color的属性,而是它的对象
enum Color {
    //只有对象列表,可省略最后一个对象后的;
    //对象后面没有“(参数列表)”就是调用无参构造
    RED, GREEN, BLUE
}

//SPRING、SUMMER、AUTUMN、WINTER就是枚举Season的对象
enum Season {
    //对象列表必须写在类的前面,多个对象之间用,隔开,末尾对象;结束
    //对象后面有“(参数列表)”就是调用有参构造
    SPRING("春天", "春暖花开"),
    SUMMER("夏天", "烈日炎炎"),
    AUTUMN("秋天", "秋高气爽"),
    WINTER("冬天", "白雪皑皑"); 

    //声明Season对象的属性:使用 private final 修饰
    private final String seasonDesc;
    private final String seasonName;

    //私有化Season类的构造器,并给对象属性赋值
    private Season(String seasonName, String seasonDesc) {
        this.seasonName = seasonName;
        this.seasonDesc = seasonDesc;
    }

    //其他需求
    //获取枚举的对象的属性
    public String getSeasonName() {
        return seasonName;
    }

    public String getSeasonDesc() {
        return seasonDesc;
    }

    //一般不用重写toString
}

public class SeasonTest {
    public static void main(String[] args) {
        Color blue = Color.BLUE;
        System.out.println(blue); //BLUE
        System.out.println(Color.class.getSuperclass()); //class java.lang.Enum

        Season summer = Season.SUMMER;
        System.out.println(summer); //SUMMER
        System.out.println(Season.class.getSuperclass()); //class java.lang.Enum
        
        Season s = Season.SPRING;
        switch(s) {
            case SPRING:
                System.out.println("春暖花开");
                break;
            case SUMMER:
                System.out.println("烈日炎炎");
                break;
            case AUTUMN:
                System.out.println("秋高气爽");
                break;
            case WINTER:
                System.out.println("白雪皑皑");
                break;
        }
    }
}

3 内部类中使用枚举

可以在Java内部类中使用枚举,可以通过在内部类中定义枚举类型来实现。

public class Outer {
    private int x;

    public void doSomething() {
        Inner inner = new Inner();
        inner.doSomethingElse();
    }

    private class Inner {
        private void doSomethingElse() {
            Status status = Status.IN_PROGRESS;
            // ...
        }

        private enum Status {
            IN_PROGRESS,
            COMPLETED,
            FAILED
        }
    }
}

4 迭代枚举元素

在Java中,我们可以使用迭代器(Iterator)来枚举集合中的元素。

enum Color
{
    RED, GREEN, BLUE;
}
public class MyClass {
  public static void main(String[] args) {
    for (Color myVar : Color.values()) {
      System.out.println(myVar);
    }
  }
}

5 switch中使用枚举类

enum Color
{
    RED, GREEN, BLUE;
}
public class MyClass {
  public static void main(String[] args) {
    Color myVar = Color.BLUE;
    
    switch(myVar) {
      case RED:
        System.out.println("红色");
        break;
      case GREEN:
         System.out.println("绿色");
        break;
      case BLUE:
        System.out.println("蓝色");
        break;
    }
  }
}

6 枚举的方法

6.1 Enum中的所有方法

关于Enum类中的所有方法我以表格的方式列举出来!

返回值

方法

描述

String

name()

获取枚举成员的名称

static T

valueOf(Class<T> enumType, String name)

获取指定枚举成员名称和类型的枚举成员

String[]

values()

获取枚举成员的所有值

int

compareTo(E o)

比较此枚举与指定对象的顺序

int

hashCode()

获取枚举成员的哈希值

int

ordinal()

获取枚举成员的序数(第一个枚举成员位置为0)

String

toString()

返回枚举成员名称

Class<E>

getDeclaringClass()

获取枚举成员的类对象

6.2 name和toString

关于name方法和toString方法,其实很简单。name()就是根据枚举成员来获取该枚举成员的字符串名称。而同String方法也是用来获取枚举成员的字符串名称。虽然作用都是相同的,但是name方法是用final修饰的不能被重写,而toString是可以被重写的。这里我们还使用季节的案例来演示,打印结果并放在了代码后面的注释中,如下:

System.out.println(Season.SUMMER.name());            //SUMMER 
System.out.println(Season.SUMMER.toString());        //SUMMER

6.3 valueOf

此方法的作用是传入一个字符串,然后将它转换成对应的枚举成员。这里传入的字符串必须与定义的枚举成员的名称一致,严格区分大小写。如果传入的字符串并没有找到其对应的枚举成员对象,就会抛出异常。如下:

System.out.println(Season.valueOf("WINTER"));            //WINTER 
System.out.println(Season.valueOf("WIN"));             //java.lang.IllegalArgumentException

6.4 values

values方法的名字中就带有一个s,再加上它的返回值是一个字符串数组。所以我们就可以得出它的作用是获取枚举成员的所有值,这些值并以数组的形式存储。

Season[] seasons = Season.values();
for (Season season : seasons) {
  System.out.print(season + " ");
}
//SPRING SUMMER AUTUMN WINTER

6.5 ordinal

该方法是获取枚举成员的序数,其第一个枚举成员位置为0。其实,为了好理解的话,可以把它看作数组中的索引。数组中的第一个元素位置同样也是从0开始。那我们打印一下,看看结果如何,如下:

//获取指定枚举成员的次序
System.out.println(Season.SUMMER.ordinal()); 
//获取所有成员的次序 
Season[] seasons = Season.values(); 
for (Season s : seasons) {     
    System.out.println(s + " -> " + s.ordinal()); 
}

//1
//SPRING -> 0
//SUMMER -> 1
//AUTUMN -> 2
//WINTER -> 3

6.6 compareTo

compareTo方法相信我们已经是很熟悉了。其作用就是用来比较的。但是在枚举类中它比较的是什么呢?实际上compareTo方法比较的是两个枚举成员的次序数,并返回次序相减后的结果。

首先,我们要知道SUMMER的次序数为1,WINTER的次序数为3。当使用前者比较后者,打印的结果是前者与后者相减后的差值,即1-3=-2

System.out.println(Season.SUMMER.compareTo(Season.WINTER));           
//-2

7 枚举实现单例

枚举单例因为其功能完善,使用简洁,无偿的提供了序列化机制,在面对复杂的序列化或者反射攻击时依然可以绝对防止多次实例化等优点。

public enum  DataSourceEnum {
    DATASOURCE;
    private DBConnection connection = null;
    private DataSourceEnum(){
        connection = new DBConnection();
    }
    public DBConnection getConnection(){
        return connection;
    }
}

8 枚举的优点

1 增强代码可读性: 枚举可以让你代码看起来很舒服,而且常量统一管理起来,当项目很大的时候很容易管理。

2 传递参数错误: 可以减少参数传递的错误性

3 去除equals两者判断 由于常量值地址唯一,使用枚举可以直接通过“==”进行两个值之间的对比,性能会有所提高。

4 编译优势(与常量类相比) 常量类编译时,常量被直接编译进二进制代码中,常量值在升级中变化后,需要重新编译引用常量的类,因为二进制代码中存放的是旧值。 枚举类编译时,没有把常量值编译到代码中,即使常量值发生改变,也不会影响引用常量的类。

5 修改优势(与常量类相比) 枚举类编译后默认final class,不允许继承可防止被子类修改。常量类可被继承修改、增加字段等,易导致父类不兼容。

6 枚举型可直接与数据库交互

7 Switch语句优势 使用int、String类型switch时,当出现参数不确定的情况,偶尔会出现越界的现象,这样我们就需要做容错操作(if条件筛选等),使用枚举,编译期间限定类型,不允许发生越界。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表