第九章:Java_枚举类和注解

一、枚举类

1.如何自定义枚举类。 枚举类:类的对象是有限个的,确定的。

  • 1.1 私有化类的构造器,保证不能在类的外部创建其对象
  • 1.2 在类的内部创建枚举类的实例。声明为:public static final
  • 1.3 若类有属性,那么属性声明为:private final 。此属性在构造器中赋值。

2.使用enum关键字定义枚举类

  • 2.1其中常用的方法:values() valueOf(String name);
  • 2.2枚举类如何实现接口 :①让类实现此接口,类的对象共享同一套接口的抽象方法的实现。②让类的每一个对象都去实现接口的抽象方法,进而通过类的对象调用被重写的抽象方法时,执行的效果不同
public class TestSeason1 {
    public static void main(String[] args) {
        Season1 spring = Season1.SPRING;
        System.out.println(spring);
        spring.show();
        System.out.println(spring.getSeasonName());

        System.out.println();
        //1.values()
        Season1[] seasons = Season1.values();
        for(int i = 0;i < seasons.length;i++){
            System.out.println(seasons[i]);
        }
        //2.valueOf(String name):要求传入的形参name是枚举类对象的名字。
        //否则,报java.lang.IllegalArgumentException异常
        String str = "WINTER";
        Season1 sea = Season1.valueOf(str);
        System.out.println(sea);
        System.out.println();

        Thread.State[] states = Thread.State.values();
        for(int i = 0;i < states.length;i++){
            System.out.println(states[i]);
        }
        sea.show();

    }
}
interface Info{
    void show();
}
//枚举类
enum Season1 implements Info{
    SPRING("spring", "春暖花开"){
        public void show(){
            System.out.println("春天在哪里?");
        }
    },
    SUMMER("summer", "夏日炎炎"){
        public void show(){
            System.out.println("生如夏花");
        }
    },
    AUTUMN("autumn", "秋高气爽"){
        public void show(){
            System.out.println("秋天是用来分手的季节");
        }
    },
    WINTER("winter", "白雪皑皑"){
        public void show(){
            System.out.println("冬天里的一把火");
        }
    };

    private final String seasonName;
    private final String seasonDesc;

    private Season1(String seasonName,String seasonDesc){
        this.seasonName = seasonName;
        this.seasonDesc = seasonDesc;
    }
    public String getSeasonName() {
        return seasonName;
    }
    public String getSeasonDesc() {
        return seasonDesc;
    }

    @Override
    public String toString() {
        return "Season [seasonName=" + seasonName + ", seasonDesc="
                + seasonDesc + "]";
    }
//  public void show(){
//      System.out.println("这是一个季节");
//  }
}

【来源其他博文:】
枚举(enum)类型是Java 5新增的特性,它是一种新的类型,允许用常量来表示特定的数据片断,而且全部都以类型安全的形式来表示。

1、常量的使用
在JDK1.5之前,我们定义常量都是:public static fianl….。现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法。

public enum Color {    
     RED, GREEN, BLANK, YELLOW 
}

使用:

public class B {
    public static void main(String[] args) {
        System.out.println( isRed( Color.BLANK ) ) ;  //结果: false
        System.out.println( isRed( Color.RED ) ) ;    //结果: true

    }
    static boolean isRed( Color color ){
        if ( Color.RED.equals( color )) {
            return true ;
        }
        return false ;
    }
}

或者 switch 的使用:

public class B {
    public static void main(String[] args) {
        showColor( Color.RED );
    }
    static void showColor(Color color){
        switch ( color ) {
        case BLANK:
            System.out.println( color );
            break;
        case RED :
            System.out.println( color );
            break;
        default:
            System.out.println( color );
            break;
        }        
    }
}

2、自定义函数

public enum Color {   
     RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);   
    private String name ;
    private int index ;  
    private Color( String name , int index ){
        this.name = name ;
        this.index = index ;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getIndex() {
        return index;
    }
    public void setIndex(int index) {
        this.index = index;
    }
}

使用:

public class B {
    public static void main(String[] args) {
        //输出某一枚举的值
        System.out.println( Color.RED.getName() );
        System.out.println( Color.RED.getIndex() );
        //遍历所有的枚举
        for( Color color : Color.values()){
            System.out.println( color + "  name: " + color.getName() + "  index: " + color.getIndex() );
        }
    }
}

结果:
红色
1
RED name: 红色 index: 1
GREEN name: 绿色 index: 2
BLANK name: 白色 index: 3
YELLO name: 黄色 index: 4

===================================

我们现在来深入了解下枚举。
先参考几篇文章:

  • ①深入理解Java枚举类型(enum)
  • ②Java 中的枚举 (enum)

在①中这样讲到。如下代码:

public class EnumDemo {
    public static void main(String[] args){
        //直接引用
        Day day =Day.MONDAY;
    }
}
//定义枚举类型
enum Day {
    MONDAY, TUESDAY, WEDNESDAY,
    THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

反编译可以看到,是这样的:

//反编译Day.class
final class Day extends Enum
{
    //编译器为我们添加的静态的values()方法
    public static Day[] values()
    {
        return (Day[])$VALUES.clone();
    }
    //编译器为我们添加的静态的valueOf()方法,注意间接调用了Enum也类的valueOf方法
    public static Day valueOf(String s)
    {
        return (Day)Enum.valueOf(com/zejian/enumdemo/Day, s);
    }
    //私有构造函数
    private Day(String s, int i)
    {
        super(s, i);
    }
     //前面定义的7种枚举实例
    public static final Day MONDAY;
    public static final Day TUESDAY;
    public static final Day WEDNESDAY;
    public static final Day THURSDAY;
    public static final Day FRIDAY;
    public static final Day SATURDAY;
    public static final Day SUNDAY;
    private static final Day $VALUES[];

    static 
    {    
        //实例化枚举实例
        MONDAY = new Day("MONDAY", 0);
        TUESDAY = new Day("TUESDAY", 1);
        WEDNESDAY = new Day("WEDNESDAY", 2);
        THURSDAY = new Day("THURSDAY", 3);
        FRIDAY = new Day("FRIDAY", 4);
        SATURDAY = new Day("SATURDAY", 5);
        SUNDAY = new Day("SUNDAY", 6);
        $VALUES = (new Day[] {
            MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
        });
    }
}

从反编译的代码可以看出编译器确实帮助我们生成了一个Day类(注意该类是final类型的,将无法被继承)而且该类继承自java.lang.Enum类,该类是一个抽象类(稍后我们会分析该类中的主要方法),除此之外,编译器还帮助我们生成了7个Day类型的实例对象分别对应枚举中定义的7个日期,这也充分说明了我们前面使用关键字enum定义的Day类型中的每种日期枚举常量也是实实在在的Day实例对象,只不过代表的内容不一样而已。

现在能明白:使用关键字enum定义的枚举类型,在编译期后,将转换成为一个实实在在的类,而在该类中,会存在每个在枚举类型中定义好变量的对应实例对象,如上述的MONDAY枚举类型对应public static final Day MONDAY;,同时编译器会为该类创建两个方法,分别是values()和valueOf()。

所以最前面的关于季节的代码:

public class Season1Demo{
    public static void main(String[] args) {
        Season spring = Season.WINTER;
        spring.show();
        Season.SPRING.show();
        Season.AUTUMN.show();
    }
}

interface Info {
    void show();
}

// 枚举类
enum Season implements Info {
    SPRING("spring", "春暖花开") {
//      public void show() {
//          System.out.println("春天在哪里?");
//      }
    },
    SUMMER("summer", "夏日炎炎") {
        //该实例重写了 show 方法
        public void show() {
            System.out.println("生如夏花");
        }
    },
    AUTUMN("autumn", "秋高气爽") {
        public void show() {
            System.out.println("秋天是用来分手的季节");
        }
    },
    WINTER("winter", "白雪皑皑") {
        public void show() {
            System.out.println("冬天里的一把火");
        }
    };

    private final String seasonName;
    private final String seasonDesc;

    private Season(String seasonName, String seasonDesc) {
        this.seasonName = seasonName;
        this.seasonDesc = seasonDesc;
    }

    public String getSeasonName() {
        return seasonName;
    }

    public String getSeasonDesc() {
        return seasonDesc;
    }

    @Override
    public String toString() {
        return "Season [seasonName=" + seasonName + ", seasonDesc=" + seasonDesc + "]";
    }

     public void show(){
         System.out.println("这是一个季节");
     }
}

结果:

冬天里的一把火
这是一个季节
秋天是用来分手的季节

我个人小结:枚举Season最后转换成了Season类(继承了Enum类),然后在该类中定义好了类型为Season的成员变量SPRINGSUMMERAUTUMNWINTER并实例化。
在引用另外看到的篇文章写道的:

enum这个关键字,可以理解为跟class差不多,这也个单独的类。可以看到,上面的例子里面有属性,有构造方法,有getter,也可以有setter,但是一般都是构造传参数。还有其他自定义方法。那么在这些东西前面的,以逗号隔开的,最后以分号结尾的,这部分叫做,这个枚举的实例。也可以理解为,class new 出来的实例对象。这下就好理解了。只是,class,new对象,可以自己随便new,想几个就几个,而这个enum关键字,他就不行,他的实例对象,只能在这个enum里面体现。也就是说,他对应的实例是有限的。这也就是枚举的好处了,限制了某些东西的范围,举个栗子:一年四季,只能有春夏秋冬,你要是字符串表示的话,那就海了去了,但是,要用枚举类型的话,你在enum的大括号里面把所有的选项,全列出来,那么这个季节的属性,对应的值,只能在里面挑。不能有其他的。

所以:

SPRING("spring", "春暖花开") {
        public void show() {
            System.out.println("春天在哪里?");
        }
    },

该代码相当就是new出了Season对象并实例化,该如果这里没写show()方法则调用的Season实现的show()方法,但这里重新定义了,相当于覆盖了show()方法。

再看一个例子(包含抽象方法的枚举类):

定义一个 Operation 枚举类,有4个枚举值PLUS、MINUS、TIMES、DIVIDE,分别代表加、减、乘、除,该枚举类有一个 calculate() 方法,用于完成计算。

public enum Operation {
    // 用于执行加法运算
    PLUS { // 花括号部分其实是一个匿名内部子类
        @Override
        public double calculate(double x, double y) {
            return x + y;
        }
    },

    // 用于执行减法运算
    MINUS { // 花括号部分其实是一个匿名内部子类

        @Override
        public double calculate(double x, double y) {
            // TODO Auto-generated method stub
            return x - y;
        }
    },

    // 用于执行乘法运算
    TIMES { // 花括号部分其实是一个匿名内部子类
        @Override
        public double calculate(double x, double y) {
            return x * y;
        }
    },

    // 用于执行除法运算
    DIVIDE { // 花括号部分其实是一个匿名内部子类
        @Override
        public double calculate(double x, double y) {
            return x / y;
        }
    };

    //为该枚举类定义一个抽象方法,枚举类中所有的枚举值都必须实现这个方法
    public abstract double calculate(double x, double y);
}

从上可以看出,掌握、理解枚举,重要要知道枚举、和枚举变量的实质是什么
枚举最后转换就是一个特殊的类,其中的枚举变量就是实例化对象。可以就这么看:

public class HelloDemo2 {
    public static void main(String[] args) {
        Season1 SPRING = new Season1("spring", "春暖花开") {
             public void show() {
                 System.out.println("春天在哪里?");
            };
        };
        SPRING.show();

    }
}

interface Info1{
    void show();
}

class Season1 implements Info1{

    private  String seasonName;
    private  String seasonDesc;

    public Season1(String seasonName, String seasonDesc) {
        this.seasonName = seasonName;
        this.seasonDesc = seasonDesc;
    }

    @Override
    public void show() {
        System.out.println("这是一个季节");
    }
}

二、注解Annotation

1.JDK提供的常用的三个注解

@Override: 限定重写父类方法, 该注释只能用于方法
@Deprecated: 用于表示某个程序元素(类, 方法等)已过时
@SuppressWarnings: 抑制编译器警告

2.如何自定义注解
以SuppressWarnings为例进行创建即可

3.元注解:可以对已有的注解进行解释说明。
第九章:Java_枚举类和注解_第1张图片

Retention: SOURCE CLASS RUNTIME
Target:
Documented:javadoc
Inherited

第九章:Java_枚举类和注解_第2张图片

你可能感兴趣的:(后端,[JavaSE,基础],JAVA基础,java,enum,annotation,枚举类,注解)