知识点
背景
1、案例引申
一些程序在运行时要求数据不能是任意的,必须是一定范围内的值。jdk5 以前采用自定义类常量来解决,而jdk5 以后出现了枚举。
假如有成绩A B C D E。 JDK5以前会以下面的方式定义
class Grade{
private Grade(){}//1 私有构造
// 2 规定只能访问特定的值
public static final Grade A=new Grade();
public static final Grade B=new Grade();
public static final Grade C=new Grade();
public static final Grade D=new Grade();
public static final Grade E=new Grade();
}
//测试类中才能达到使用特定的值
public static void main(String[] args){
// 测试类中使用值通过这种方式访问
System.out.println(Grade.A);
System.out.println(Grade.B);
...
}
JDK5以后会以以下面的方式定义
enum Grade{
A ,B,C,D,E;
}
public static void main(String[] args){
// 测试类中使用值通过这种方式访问
System.out.println(Grade.A);
System.out.println(Grade.B);
...
}
对比发现,写代码时少了很多语句声明,舒服多啦~
枚举
1、枚举的构造
如上的案例引申,直接定义了A、B、C、D、E 5个枚举常量对象。其实枚举类和普通类一样,默认也是无参构造,这里进行代码修改,添加带参数的构造。
enum Grade{
A("100-99") ,B("99-80"),C("80-70"),D("70-60");
private String value; //定义个类的成员
Grade(String value){//构造
this.value=value;
}
public String getValue(){
return value;
}
}
//测试
public static void main(String[] args){
//简单的对象调用方法
System.out.println(Grade.A.getValue());
}
总结:
- 枚举中的构造必须为私有(private)或者不写(默认为private )
原因:构造方法为private目的就是为了不让你用new来创建该类型的对象,而枚举类型的个数必须是确定的(根据枚举体的作用定义)所以它必须是private- 枚举的成员是可以有的,和普通的成员一样定义使用。
- 枚举的方法可以有的,和普通的方法一样定义使用。
注意:定义枚举类实成员命名规范,一般按照常量的书写形式-大写。ps:枚举成员为什么不能是数字?
变量的命名规范规定变量只能以$、_、和字母开头开头的
2 、枚举类的成员
两类:
1、枚举类实例
定义方式相当于我们定义普通变量方式(int a,b,c;)只不过定义的时候枚举类实例就完成了初始化。
2、普通定义的成员
定义方式和我们在普通类中定义成员一样,使用方式也一样。
3、带抽象方法的枚举类
enum Grade{
A("100-99") ,B("99-80"),C("80-70"),D("70-60");
private String value;
Grade(String value){
this.value=value;
}
public String getValue(){
return value;
}
public String getGrade(){
return "优秀";
}
}
上面的 getGrade方法,如果在测试类中使用 Grade.A.getGrade(),A换为B,C…我们得到的都是“优秀”,如下改善添加抽象方法:
enum Grade{
// A 代表的就是枚举对象,所以必须实现类中定义的抽象方法
A("100-99"){
@Override
public String getGrade() {
return "优秀";
}
} ,
B("99-80") {
@Override
public String getGrade() {
return "良好";
}
},
C("80-70") {
@Override
public String getGrade() {
return "及格";
}
},
D("70-60") {
@Override
public String getGrade() {
return "不及格";
}
};
private String value;
Grade(String value){
this.value=value;
}
public String getValue(){
return value;
}
// 抽象方法
public abstract String getGrade();
}
4 、枚举特有的方法
这里参看官方文档最合适不过了。emmmmm~
常用的:
- name()返回枚举类的常量值,和直接打印类名.枚举值一样(toString方法已经实现)
- ordinal ()返回枚举的索引序数,遍历枚举值会用到
- toString()枚举类已经重写,直接返回实例的字符串形式。(看看name方法和toString的作用差不多)
5、实现接口和继承问题
(1)接口的实现
和普通类实现接口一样
(2)继承问题
所有的枚举都继承自java.lang.Enum类。由于Java 不支持多继承,所以枚举对象不能再继承其他类。
Enum类源码:
/**
* This is the common base class of all Java language enumeration types. 这是所有枚举的基类
* @param <E> The enum type subclass
* @author Josh Bloch
* @author Neal Gafter
* @see Class#getEnumConstants()
* @see java.util.EnumSet 枚举set 参看java提供的枚举set集合
* @see java.util.EnumMap 枚举map 参看java提供的枚举map集合
* @since 1.5 java 1.5添加枚举
*/
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable {
...
...
}
枚举的应用
1、枚举的单例:
/**
* Created by sunnyDay on 2019/7/22 16:13
*/
class Singleton{
//私有构造
private Singleton() {
}
// 通过枚举提供单例
enum SomeThing {
INSTANCE;
private Singleton singleton;
SomeThing() { //枚举的构造默认就是私有
singleton = new Singleton();
}
public Singleton getSingleton() {
return singleton;
}
}
public static void main(String[] args) {
System.out.println(SomeThing.INSTANCE.getSingleton());
System.out.println(SomeThing.INSTANCE.getSingleton());
System.out.println(SomeThing.INSTANCE.getSingleton());
// log:
//javapck.Singleton@330bedb4
//javapck.Singleton@330bedb4
//javapck.Singleton@330bedb4
}
}
首先,在枚举中明确了构造方法限制为私有,在我们访问枚举实例时会执行构造方法,同时每个枚举实例都是static final类型的,也就表明只能被实例化一次。在调用构造方法时,我们的单例被实例化。 也就是说,因为enum中的实例被保证只会被实例化一次,所以我们的INSTANCE也被保证实例化一次。更多单利参考:单例设计模式(Singleton)
2、枚举应用于switch语句
/**
* Created by sunnyDay on 2019/7/22 16:37
*/
public class Test {
public void testEnum(Grade grade) {
switch (grade) {
case A: //注意此处Grade.A 会报错
System.out.println("优秀");
break;
case B:
System.out.println("良好");
break;
default:
}
}
}
public enum Grade {
A,B
}
小结
- 枚举类是一种特殊的java类
- 枚举类中声明的每一个枚举值代表一个枚举类的实例对象
- 与java的普通类一样,在声明枚举类时也可以声明属性、方法,构造函数,但是构造函数必须为私有(原因参上有解释)
- 枚举类也可以实现接口。不能继承其他类。
- jdk5中扩展了switch语句,除了可以接受int byte char short(没有long)外,还可以接受枚举类型,
- 枚举若只有一个值则可以当做单利设计模式使用
end
参考文章: