深入剖析java反射原理

枚举类

背景及定义

自定义枚举类与enmu对比

  • 在上一篇java高级之多线程中,生命周期的线程的状态中,有这样的一段代码,分别代表线程的新建状态运行状态阻塞状态等待状态超时等待状态终止状态
public enum State {
    
    
        NEW,
        RUNNABLE,
        BLOCKED,
        WAITING,
        TIMED_WAITING,
        TERMINATED;
}
  • 那么假如现在不用枚举类或者说,在枚举类的用法还没发行之前,我们想表示线程的这几种状态时,又该怎么写呢?经过一番思考,它应该符合以下几个条件:
  • 这些状态是有限个的,也就是说我们设计的线程状态一共有6种;
  • 这6种状态都应该是State类的实例;
  • 除下自己定义的这6种状态外,不应该在State类外面实例化一个状态,换句话说,状态一共就6种,并且已经在State类中实例化好了。那么该类的构造方法应该是私有private的;
  • 状态应该是静态static的,这样可以通过类名直接调用;
  • 状态是常量,用final修饰。
public class State {
    
    
    //私有的构造方法
    private State(){
    
    }
    //实例化6种状态
    public static final State NEW = new State();
    public static final State RUNNABLE = new State();
    public static final State BLOCKED = new State();
    public static final State WAITING = new State();
    public static final State TIMED_WAITING = new State();
    public static final State TERMINATED = new State();

    //想打印一下当前线程的名字
    public static void printNowState(State state){
    
    
        if(state == NEW)
            System.out.println("NEW");
        else if(state == RUNNABLE)
            System.out.println("RUNNABLE");
        else if(state == BLOCKED)
            System.out.println("BLOCKED");
        else if(state == WAITING)
            System.out.println("WAITING");
        else if(state == TIMED_WAITING)
            System.out.println("TIMED_WAITING");
        else if(state == TERMINATED)
            System.out.println("TERMINATED");
    }
}

class Teststate {
    
    
    public static void main(String[] args) {
    
    
        //新建状态
        System.out.println("线程的新建状态" + State.NEW);
        //打印出状态名,重写toString也打印不出来当前状态名字,因为toString方法没有参数。
        State.printNowState(State.NEW);
    }
}

枚举类

简单介绍

  • 类的对象只有有限个,并且是确定的。例如:星期、季节、性别、线程状态等。
  • 相对于自定义常量来说,枚举类更加直观,类型安全。

枚举类特点

  • 私有化类的构造器,无法在类的外部创建对象;

  • 枚举类的实例。声明为:public static final

  • 枚举类对象的属性使用 private final 修饰,不允许被修改;

  • 枚举类的属性应该在构造器中为其赋值;

  • 若枚举类显式的定义了带参数的构造器, 则在列出枚举值时也必须对应的传入参数。

使用说明

  • 枚举类使用的是enum关键字,继承自java.lang.Enum,且无法被继承;
  • 必须在枚举类的第一行声明枚举类对象;
  • 枚举类的所有实例必须在枚举类中显式列出,(用“,” 分隔、用“ ;” 结尾);
  • 定义的每个实例都是引用类型的唯一实例;
  • 只能定义出enum的实例,而无法通过new操作符创建enum的实例;
  • 列出的实例系统会自动添加 public static final 修饰;
  • 使用enum变量的时候,【类名.变量名】;
  • 可以将enum类型用于switch语句。

枚举类反编译

  • 如上使用枚举类定义线程状态时,编译器编译出的class文件类似于这样:
//该类继承自Enum,被标记为final class
public final class State extends Enum {
    
     
    //每个实例均为全局唯一,均为static final修饰。
    public static final State NEW = new State();
    public static final State RUNNABLE = new State();
    ....
    public static final State TERMINATED = new State();
    // 构造器私有化,在类的外部无法调用new操作符。
    private State() {
    
    }
}

主要方法

  • 如上,我们定义出线程状态的枚举类后,使用枚举类State的常用方法有:

    image-20200715224456355

  • 方法实战

        public static void main(String[] args) {
          
          
            //返回枚举类对象的名字,枚举类对象的名字不用重写toString
            System.out.println(State.NEW.toString());
            System.out.println("============我是分隔符=============");
            //返回所有的枚举类对象构成的数组
            State[] states = State.values();
            for (int i = 0; i < states.length; i++) {
          
          
                System.out.println(states[i]);
            }
            System.out.println("============我是分隔符=============");
            //valueOf(String objName):返回枚举类中对象名是objName的对象。传入的objName应该存在,否则抛异常IllegalArgumentException
            State state = State.valueOf("NEW");
            System.out.println(state);  
          	System.out.println("============我是分隔符=============");
            //枚举的switch用法
            State scase = State.BLOCKED;
            switch (scase) {
          
          
                case NEW:
                    System.out.println("我的线程状态是" + scase.toString());
                    break;
                case RUNNABLE:
                    System.out.println("我的线程状态是" + scase.toString());
                    break;
                case BLOCKED:
                    System.out.println("我的线程状态是" + scase.toString());
                    break;
                case WAITING:
                    System.out.println("我的线程状态是" + scase.toString());
                    break;
                case TIMED_WAITING:
                    System.out.println("我的线程状态是" + scase.toString());
                    break;
                case TERMINATED:
                    System.out.println("我的线程状态是" + scase.toString());
                    break;
                default:
                    throw new RuntimeException("查不到定义的线程状态" + scase.toString());
            }
        }
    
  • 控制台的输出

    image-20200715231411753

总结

  • 枚举类的出现是为了解决类的对象是有限个并且是确定的情况;
  • 构造器私有化;
  • 必须首行声明枚举类对象,逗号隔开,分号结尾。

原创不易,欢迎转载,转载时请注明出处,谢谢!
作者:潇~萧下

猜你喜欢

转载自blog.csdn.net/W_ryxj000/article/details/107774976