今天看源码,有个项目他把很多数据放在产量类里边,后来想想为啥不放到枚举里边呢?这就有了上面这个题目

找了很多资料,这里有一篇资料让我明晰:

这是地址:学习笔记——枚举(枚举类、Enum类、枚举结构(接口、抽象类))_枚举和枚举类_微凉归期的博客-CSDN博客

下面摘抄一下上面的文章

定义枚举类

枚举是特殊的多例设计,其与表达意义相同。在jdk1.5之后提供enum关键字,利用此关键字可以实现枚举定义。
例子:定义一个枚举

package a.a.a;
enum Color{ //枚举
 红色,绿色,蓝色;//实例化对象
}
public class Java {
public static void main(String[] args) {
	Color x=Color.红色;
	System.out.println(x);
  }
}

此时采用多列设计模式会涉及很多代码,其中涉及到了构造方法私有化,静态方法等。多例设计与枚举实现相同效果,但是枚举可以在编译过程中检测到实例化对象是否存在*。
例子:枚举定义有方法可以获取所以实例化对象的值

package a.a.a;
enum Color{ //枚举
红色,绿色,蓝色;//实例化对象
}
public class Java {
public static void main(String[] args) {
	for (Color x:Color.values() ){
		System.out.println(x);
	  }
	}
}

输出:
红色
绿色
蓝色
例子:观察枚举与switch进行判断处理

package a.a.a;
enum Color{ //枚举
红色,绿色,蓝色;//实例化对象
}
public class Java {
public static void main(String[] args) {
	Color x=Color.红色;
	switch(x){ //直接枚举
		case 红色:
		System.out.println("red");
		break;
		case 绿色:
		System.out.println("green");
		break;
		case 蓝色:
		System.out.println("blue");
		break;
	}
 	}
}

输出:red


Enum类

严格意义上枚举并不属于一种新的结构,其本质相当于一个类,这个类默认继承了Enum类。Enum类定义如下:
public abstract class Enum<E extends Eunm>
extends Object
implements Comparable,Serializable
现在定义的枚举类的类型就是Enum中所使用的E类型。

例子:观察Enum类存在

package a.a.a;
enum Color{ //枚举
红色,绿色,蓝色;//实例化对象
}
public class Java {
public static void main(String[] args) {
	for (Color x:Color.values()){
	System.out.println(x.ordinal()+"--"+x.name());  //输出序号和名称
	}
}
}

输出结果:
0–红色
1–绿色
2–蓝色
序号是根据对象的顺序发生变化的。
观察enum与Enum的区别?
·enum从jdk1.5之后提供的关于定义枚举的关键字;
·Enum是一个无法直接看见的抽象类,使用enum关键字定义的类就默认继承了此类。


定义枚举结构

枚举本身属于一种多例设计模式,那么在一个类的定义的结构非常多。例如:构造方法、普通方法、属性等。这些内容可以在枚举直接定义,但是需要注意的是多例设计中构造方法私有化,枚举类中定义的构造方法不能非私有化定义(即public不可使)。
例子:枚举类中定义多种结构

package a.a.a;
  enum Color{ //枚举类
红色(""),绿色("绿"),蓝色("蓝");//实例化对象枚举对象,必须写在第一行
private String title;
private Color(String title){
    this.title=title;
    }
public String toString(){
    return this.title;
	}
}
public class Java {
public static void main(String[] args) {
	for (Color x:Color.values()){
	System.out.println(x.ordinal()+"--"+x.name()+"--"+x);
	}
    }
}

 

输出结果:
0–红色–红
1–绿色–绿
2–蓝色–蓝
除了基本结构之外,枚举也可以实现接口继承。
例子:枚举实现接口

package a.a.a;
interface IMessage{
public String getMessage();
  }
enum Color implements IMessage{ //枚举类
红色("红色"),绿色("绿色"),蓝色("蓝色");//实例化对象枚举对象,必须写在第一行
private String title;
private Color(String title){
    this.title=title;
  }
public String toString(){
    return this.title;
  }
public String getMessage(){
	return this.title;
  }
}
public class Java {
public static void main(String[] args) {
	IMessage x=Color.红色;
	System.out.println(x.getMessage());
	}
}

 

枚举可以直接定义在抽象方法,并且要求每一个枚举对象独立覆写实现此方法。


枚举应用案例

假设现在定义有一个Person类,类中属性有性别,不希望用户随意输入,只有男女两种选择。

enum Sex{
MALE("男"),FEMALE("女");
private String title;
private Sex(String title){
    this.title=title;
}
public String toString(){
    return this.title;
	}
}
class Person{
private String name;
private int age;
private Sex sex;//性别
public Person(String name,int age,Sex sex){
	this.name=name;
	this.age=age;
	this.sex=sex;
}
public String toString(){
    return "姓名:"+this.name+"、年龄:"+this.age+"、性别:"+this.sex;
	}
}
public class Java {
public static void main(String[] args) {
	Person a=new Person("温情",19,Sex.FEMALE);
	System.out.println(a.toString());
	System.out.println(new Person("温宁",18,Sex.MALE).toString());
    }
}

输出结果:
姓名:温情、年龄:19、性别:女
姓名:温宁、年龄:18、性别:男

 

 

看完上面的解释以及输出,你应该对枚举和枚举类有了很深的了解。枚举类中的第一行,就是实例化的枚举对象。枚举类都有自己的构造函数,所以实例化的时候会调用自己的构造函数。然后如果要输出的话,重写一下toString()方法,将值输出,就可以获得该对象的值了。

常量类就是一个类,只不过这个类中放了很多常量,可以通过 public static final 来初始化常量,使用时可以直接通过类名来获得产量值。

 

然后我在说说各自的优缺点:

文章来自java枚举与常量类区别_常量和枚举的区别_黑旋风李鬼的博客-CSDN博客

优点

  1. 枚举相对于常量类来说定义更简单,其不需要定义枚举值,而常量类中的每个常量必须要手动添加值。   【有时候我们可以在枚举类的构造函数中动手脚来实现常量类中的值的定义化,这就又引出了后面的文章 枚举类型只能通过内部的枚举常量进行初始化】
  2. 枚举作为参数使用时可以在编译时避免弱类型错误,而常量类中的常量作为参数使用时在编译时无法避免弱类型错误(譬如常量类型为 int,参数传递一个常量类中没定义的 int 值)。
  3. 枚举自动具备内置方法(如 values 方法可以获得所有值的集合来遍历,ordinal 方法可以获得排序值,compareTo 方法可以基于 ordinal 比较),而常量类默认不具备这些方法。

缺点

  1. 枚举的缺点就是不能被继承(编译后生成的类是 final class 的),也不能通过 extends 继承其他类(枚举类编译后实质就是继承了 Enum 类,Java 是单继承机制),但是定义的枚举类可以通过 implements 实现其他接口
  2. 枚举值定义完毕后除非修改重构,否则无法做扩展,而常量类可以随意继承。

关于枚举的各种,种种定义,下面这篇文章更详细,我喜欢

是枚举?还是常量?其实很好选择!_枚举和常量_windwant的博客-CSDN博客

一、什么是枚举?

首先,枚举是一种特殊的类对象,其定义如下:

{修饰符} enum 对象标识 [父接口] 枚举体

枚举类型通过一些特殊的约束,来实现其应用特性:

1、枚举不可定义为abstract 或者 final,否则会引发编译器错误。

2、枚举实现了Comparable及Serializable接口,因此可以进行比较及序列化等操作,类型定义如下:

3、枚举类型只能通过内部的枚举常量进行初始化

4、枚举类型clone方法定义为final,即不可复制,否则会抛出异常:

5、枚举类型无法通过反射机制进行初始化。

6、枚举类型需要自定义处理序列化,反序列化,默认的序列化使用会抛出异常。

7、枚举类型equals定义为final,不可自定义覆盖,同关联hashCode方法。

8、枚举类型finalize定义为final,意味着枚举实例可能永远不会被垃圾回收。

二、枚举的初始化

如下图,我们定义EnvEnum类型枚举,然后通过PROD、RELEASE、DEV枚举常量初始化了三个EnvEnum实例:

枚举常量体可以包含参数,参数会通过构造函数进行枚举类型的初始化。

枚举体相当于定义了一个内部匿名类,但是不可包含构造函数及abstract方法。

枚举类型的构造函数有以下特殊约定限制:

1、构造函数默认为private修饰(不可外部初始化构造),不可使用public 或者 protected修饰,否则会导致编译错误。

2、不可在构造函数内调用父类构造函数。

3、枚举类型会默认声明无参构造函数。

三、枚举的一些特性

1、valueOf:根据枚举常量名称查找枚举实例。

枚举类型提供根据名称查询实例方法,需要注意的是,如果查找不到匹配的实例,则会抛出异常。

2、compareTo:提供枚举实例对比方法

对比需要再同类型枚举实例间,根据枚举实例的ordinal对比实现。 

 

继续,怎么用?哪些场合用枚举,哪些用常量?查了些资料,基本上公婆都有理那种,贴一贴吧

 

 

1、概述
在编码过程中,避免不了维护一些常量。而通过这么多的项目中发现,使用方式都不尽相同。有用常量类的、有用接口的、有用枚举的,因此本文针对于常量的管理做一些讨论

2、栗子
第一种使用接口:

public interface Constants{
int AUDIT_STATUS_PASS = 1;
int AUDIT_STATUS_NOT_PASS = 2;
}
1.
2.
3.
4.
第二种使用常量类:

public class Constans{
public static final int AUDIT_STATUS_PASS = 1;
public static final int AUDIT_STATUS_NOT_PASS = 2;
}
1.
2.
3.
4.
第三种使用枚举:

@Getter
@AllArgsConstructor
public enum ChildType {

NORMAL_PARENT(0, "正规课"),
TRIAL_PARENT(1, "体验课");

private int id;
private String name;
}
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
相比较第一种和第二种其实差不多,但第一种显然更简洁,因为不用写public static final了嘛,更方便了。但是,但是,但是不建议在接口中定义常量。因为我在阅读《Effective Java》这本书中提到过:

如果某个实现了常量接口的类被修改不再需要常量了,也会因为序列化兼容原因不得不保持该实现,而且非final类实现常量接口会导致所有子类被污染

所以我个人推荐:接口中的常量, 不应该用于全局. 而应当用在与之相关的类中。这样能保持很好的层级关系和隔离性,方便分包和扩展,具体请参考spring中对常量维护的原则。
当然,刚才说了不建议把一般的常量放在接口里,所以我们可以放在常量类了,但建议常量类是final的。

什么时候使用枚举呢?其实建议使用枚举。《Effective Java》中也是推荐使用枚举代替int常量的。枚举当然是首选,另如果不用枚举,在《Effective Java》一书中,作者建议使用一般类加私有构造方法的方式,至于为什么不用接口,那就要上升到语言哲学问题了(可参考上面通俗易懂的话)。

此处个人不建议什么都使用枚举来代替常量类。比如毫无规则归类可言的一些常量:如SUCCUSS字符串、密钥串、路径等等这些,可以放在一个常量类里面糅在一起。而对于数据库中对应type、status类型字段并且是可以枚举出来的,强烈建议使用enum类型,在平时获取、使用、校验起来常量无法比拟的,而且可以很少犯错,非常大程度上增加代码的可读性,这也是为什么JDK5要推荐使用枚举类的原因吧。

最后,本人建议大家可以在设计代码的时候,多用接口规范代码,哪怕只是一个标记接口,也尽量为了长远考虑而设计出来。通过读spring、mybatis源码会发现里面不乏一些标记接口,在向上抽象归类判断的时候,非常有用。

3、使用场景
大力推荐枚举类型的使用,让他无处不在的去管理你的代码,可以让代码结构更加清晰易懂可扩展。而常量类可以收集管理一些比较杂的一些常量。而接口的中的常量,在遵循开闭原则的基础上,向上抽象管理自己的内聚的常量

4、最后
写代码也是一种艺术,结构层次好的代码可以少出bug,提高效率。用一句话总结就是:设计良好的代码结构,尽量面向元数据编程。
-----------------------------------
©著作权归作者所有:来自51CTO博客作者YourBatman的原创作品,请联系作者获取转载授权,否则将追究法律责任
【小家java】java中维护常量使用常量类?接口?还是枚举呢?
https://blog.51cto.com/u_3631118/3119739

 

 

反正我看了个大概,明白了。你明白不明白,不明白自己接着查资料去明白吧。。。。我把原来的代码的常量改成枚举了

posted on 2023-09-05 18:21  孤独斗士  阅读(11)  评论(0编辑  收藏  举报