枚举、反射

枚举

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());

枚举、反射_第1张图片

 

枚举类也可以实现接口

接口

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 personClass = person.getClass();
        // 通过内置class获取
        Class 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 objectClass = Object.class;
        // 接口
        Class serializableClass = Serializable.class;
        // 数组
        int[] a = {1,2,3};
        // 同一维度,同一个类型的字节码文件一样
        Class aClass = a.getClass();
        // 基本数据类型
        Class integerClass = int.class;
        // 注解
        Class controllerClass = Controller.class;
        // void
        Class voidClass = void.class; 
  

获取构造器

        // 根据字节码获取构造器
        // 获取字节码
        Class clazz = Object.class;
        
        // 获取public类型的所有构造器
        Constructor[] publicConstructors = clazz.getConstructors();
        // 获取public类型无参构造器
        Constructor publicWucanConstructor = clazz.getConstructor();
        // 获取public类型指定构造器(参数根据构造器的参数类型来设定)
        Constructor publicConstructor = clazz.getConstructor(int.class, double.class);
        
        // 获取所有访问修饰符的构造器
        Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
        // 获取所有访问修饰符的无参构造器
        Constructor wucanDeclaredConstructor = clazz.getDeclaredConstructor();
        // 获取所有访问修饰符的指定构造器(参数根据构造器的参数类型来设定)
        Constructor 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 superclass = clazz.getSuperclass();
        // 获取父类接口
        Class[] superInterfaces = superclass.getInterfaces();
        // 获取当前类的包
        Package aPackage = clazz.getPackage();
        // 获取当前类的注解
        Annotation[] classAnnotations = clazz.getAnnotations();

测试

黑盒测试:不需要关注代码

白盒测试:需要关注代码

junit单元测试属于白盒测试

你可能感兴趣的:(java基础,java,java-ee)