枚举
jdk1.5之前,需要自己实现枚举
自己实现枚举
public class StatusEnum {
    private final String id;
    private final String code;
    private final String name;
    private StatusEnum(String id, String code, String name){
        this.id = id;
        this.code = code;
        this.name = name;
    }
    public static final StatusEnum TODO = new StatusEnum("1","todo","待完成");
    public static final StatusEnum DONE = new StatusEnum("2","todo","已完成");
    public static final StatusEnum DOING = new StatusEnum("3","doing","正在完成");
    public String getId() {
        return id;
    }
    public String getCode() {
        return code;
    }
    public String getName() {
        return name;
    }
    @Override
    public String toString() {
        return "StatusEnum{" +
                "id='" + id + '\'' +
                ", code='" + code + '\'' +
                ", name='" + name + '\'' +
                '}';
    }
}
jdk1.5之后,提供了枚举
jdk提供的枚举
public enum StatusEnum2 {
    TODO("1","todo","待完成"),
    DONE("2","todo","已完成"),
    DOING("3","doing","正在完成");
    private final String id;
    private final String code;
    private final String name;
    StatusEnum2(String id, String code, String name) {
        this.id = id;
        this.code = code;
        this.name = name;
    }
    public String getId() {
        return id;
    }
    public String getCode() {
        return code;
    }
    public String getName() {
        return name;
    }
}枚举的父类是java.lang.Enum
没有属性的枚举
public enum StatusEnum3 {
    TODO,
    DONE,
    DOING;
}枚举类常用的方法
toString(): 返回对象名
values:静态方法,获取所有对象名
valueOf(name): 根据name或者对象
        StatusEnum3 doing = StatusEnum3.DOING;
        System.out.println(doing.toString());
        StatusEnum3[] values = StatusEnum3.values();
        for(StatusEnum3 statusEnum3: values){
            System.out.println(statusEnum3.toString());
        }
        StatusEnum3 done = StatusEnum3.valueOf("DONE");
        System.out.println(done.toString());
枚举类也可以实现接口
接口
public interface TestInterface {
    
    void show();
}
枚举类
public enum StatusEnum3 implements TestInterface{
    TODO,
    DONE,
    DOING;
    @Override
    public void show() {
        System.out.println("xxx");
    }
}
此时,枚举对象调用接口方法时,调用的是同一个方法。
如果想要每种类型的枚举调用不同的方法实现,可以这样做:
public enum StatusEnum3 implements TestInterface{
    TODO{
        @Override
        public void show() {
            // todo something
        }
    },
    DONE{
        @Override
        public void show() {
            // todo something
        }
    },
    DOING{
        @Override
        public void show() {
            // todo something
        }
    };
    
}枚举搭配switch case使用
case中不用写StatusEnum3.TODO,直接写TODO就可以了
        StatusEnum3 statusEnum3 = StatusEnum3.DOING;
        switch (statusEnum3){
            case TODO: // do something 
                break;
            case DOING: // do something 
                break;
            case DONE: // do something 
                break;
        }反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
在运行期间,如果我们要产生某个类的对象,Java虚拟机(JVM)会检查该类型的Class对象是否已被加载。如果没有被加载,JVM会根据类的名称找到.class文件并加载它。一旦某个类型的Class对象已被加载到内存,就可以用它来产生该类型的所有对象。
获取字节码信息的四种方式
1. 通过对象获取
2. 通过内置class获取
3.通过forName获取
4.通过类加载器获取
public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        // 通过对象获取
        Person person = new Person();
        Class<? extends Person> personClass = person.getClass();
        // 通过内置class获取
        Class<Person> personClass2 = Person.class;
        // 通过Class.forName获取
        Class<?> personClass3 = Class.forName("com.xy.shirotest.reflectTest.Person");
        // 通过类加载器获取
        Class<?> personClass4= Test.class.getClassLoader()
                .loadClass("com.xy.shirotest.reflectTest.Person");
    }
}获取的所有字节码都是同一个。一个类只有一个字节码信息
Class类的具体实例
1. 类
2. 接口
3. 数组
4. 基本数据类型
5. 注解
6. void
        // 可以作为Class类的实例
        // 类
        Class<Object> objectClass = Object.class;
        // 接口
        Class<Serializable> serializableClass = Serializable.class;
        // 数组
        int[] a = {1,2,3};
        // 同一维度,同一个类型的字节码文件一样
        Class<? extends int[]> aClass = a.getClass();
        // 基本数据类型
        Class<Integer> integerClass = int.class;
        // 注解
        Class<Controller> controllerClass = Controller.class;
        // void
        Class<Void> voidClass = void.class;获取构造器
        // 根据字节码获取构造器
        // 获取字节码
        Class<Object> clazz = Object.class;
        
        // 获取public类型的所有构造器
        Constructor<?>[] publicConstructors = clazz.getConstructors();
        // 获取public类型无参构造器
        Constructor<Object> publicWucanConstructor = clazz.getConstructor();
        // 获取public类型指定构造器(参数根据构造器的参数类型来设定)
        Constructor<Object> publicConstructor = clazz.getConstructor(int.class, double.class);
        
        // 获取所有访问修饰符的构造器
        Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
        // 获取所有访问修饰符的无参构造器
        Constructor<Object> wucanDeclaredConstructor = clazz.getDeclaredConstructor();
        // 获取所有访问修饰符的指定构造器(参数根据构造器的参数类型来设定)
        Constructor<Object> declaredConstructor = clazz.getDeclaredConstructor(int.class, double.class);
        // 通过构造器创建对象
        Object o1 = publicWucanConstructor.newInstance();
        // 
        Object o2 = declaredConstructor.newInstance(1, 1.2);获取属性、给属性设值
        // 获取当前类和父类中,所有被public修饰的属性
        Field[] fields = clazz.getFields();
        // 获取当前类中所有属性
        Field[] declaredFields = clazz.getDeclaredFields();
        // 根据属性名获取属性public
        Field gender = clazz.getField("gender");
        // 获取属性具体信息 ---------------------
        // 获取属性名
        String name = gender.getName();
        // 获取属性类型
        String typeName = gender.getType().getName();
        // 获取访问修饰符
        String modifier = Modifier.toString(gender.getModifiers());
        
        // 给属性设值
        Object obj = clazz.newInstance();
        gender.set(obj, "男");获取方法
        /* 获取方法 */ 
        // 获取运行时类和所有父类的public方法
        Method[] publicMethods = clazz.getMethods();
        // 根据方法名获取不带参数的public方法(运行时类和所有父类的)
        Method eat = clazz.getMethod("eat");
        // 根据方法名和参数类型获取public方法(运行时类和所有父类的)
        Method sleep = clazz.getMethod("sleep", int.class, long.class);
        // 获取运行时类所有方法
        Method[] declaredMethods = clazz.getDeclaredMethods();
        // 根据方法名获取不带参数的方法
        Method hello = clazz.getMethod("hello");
        // 根据方法名和参数类型获取方法
        Method world = clazz.getDeclaredMethod("world", String.class, double.class);
        /* 获取方法相关参数 */
        // 方法修饰符
        String methodModifier = Modifier.toString(world.getModifiers());
        // 方法返回值类型
        Class<?> returnType = world.getReturnType();
        // 方法名
        String methodName = world.getName();
        // 方法参数列表类型
        Class<?>[] parameterTypes = world.getParameterTypes();
        // 注解 只能获取RUNTIME类型的注解
        Annotation[] annotations = world.getAnnotations();
        
        /* 方法调用 */
        Object o = clazz.newInstance();
        Object invokeReturn = world.invoke(o, "zhangsan", 19.8);
获取其他信息
        // 获取运行时class的接口
        Class<?>[] interfaces = clazz.getInterfaces();
        // 获取父类
        Class<? super Object> superclass = clazz.getSuperclass();
        // 获取父类接口
        Class<?>[] superInterfaces = superclass.getInterfaces();
        // 获取当前类的包
        Package aPackage = clazz.getPackage();
        // 获取当前类的注解
        Annotation[] classAnnotations = clazz.getAnnotations();测试
黑盒测试:不需要关注代码
白盒测试:需要关注代码
junit单元测试属于白盒测试



![CodeForces..翻转魔术.[简单].[找规律]](https://img-blog.csdnimg.cn/981fffe8052f4c29b8a38d1cd3c79d42.png)















