反射机制、自定义Annotation

 java反射机制

  • 获取运行时类的完整结构
  • 可以再运行时的代码可以根据某些条件改变自身结构
  • 反射对性能有影响。
  1. 一个类在内存中只有一个class对象
  2. 一个类被加载后,类的整个结构都会被封装在class对象中。

测试1-常用反射类、方法

 

package com.fh.base;

import java.lang.reflect.*;
import java.util.*;

public class T {
    public static void main(String[] args) throws Exception {
        getGeneric();
    }

    /**
     * 获得类实例!!!
     */
    static void getInstance() throws Exception {
             /*Constructor<Stu> declaredConstructor = stuClass.getDeclaredConstructor(int.class, String.class);
        Stu stu1 = declaredConstructor.newInstance(12,"Jay");
        System.out.println("【通过构造器实现类的实例化】" + stu1);*/

        Class stuClass = Class.forName("com.fh.base.Stu");
        Stu stu = (Stu) stuClass.newInstance();
        System.out.println("【new 类的实例化】" + stu);

        System.out.println("【通过反射操作方法 Method invoke(对象,值)。为哪个对象赋值】");
        Method setName = stuClass.getDeclaredMethod("setName", String.class);
        setName.invoke(stu, "Jay");

        System.out.println("【通过反射操作方法 Method invoke(对象)。获取哪个对象的值】");
        Method getName = stuClass.getDeclaredMethod("getName");
        String name = (String) getName.invoke(stu);
        System.out.println(name);

        System.out.println("【通过反射操作属性 Field set(对象,值)");
        Field name1 = stuClass.getDeclaredField("name");
        name1.setAccessible(true);//java.lang.IllegalAccessException: Class com.fh.base.T can not access a member of class com.fh.base.Stu with modifiers "private"
        name1.set(stu, "周杰伦");
        System.out.println(stu.getName());
    }

    /**
     * 获得包信息
     */
    static void getPackeage() {
        System.out.println("【获得类所在包】");
        Class stuClass = Stu.class;
        Package aPackage = stuClass.getPackage();
        System.out.println(aPackage);
    }

    /**
     * 获得Class信息
     */
    static void getClassz() throws Exception {
        //System.out.println("【Java 类路径】" + System.getProperty("java.class.path"));
        System.out.println("【获取类的加载器】" + T.class.getClassLoader()
                + ";Object根加载器:" + Object.class.getClassLoader());

        Class<T> tClass1 = T.class;
        Class<?> tClass2 = Class.forName("com.fh.base.T");
        T t = new T();
        Class<? extends T> tClass3 = t.getClass();
        System.out.println("【一个类在内存中只有一个class对象】" + (tClass1.hashCode() == tClass2.hashCode() && tClass2.hashCode() == tClass3.hashCode()));
        System.out.println("【获得类名】" + tClass1.getName());

        T t1 = tClass1.newInstance();
        T t2 = tClass1.newInstance();
        Stu stu = Stu.class.newInstance();
        System.out.println("【类的实例化】" + (t1 == t2));
        System.out.println("【类的实例化】" + stu);


        System.out.println("【用来判断A是否是B的实例对象或者B子类的实例对象】" + (t1 instanceof T));
    }

    /**
     * 获得属性信息
     */
    static void getField() throws Exception {
        Class stuClass = Stu.class;
        System.out.println("【获取所有属性】");
        Field[] declaredFields = stuClass.getDeclaredFields();
        for (Field field : declaredFields) {
            System.out.println(field);
        }
        System.out.println("【获取public属性】");
        Field[] fields = stuClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        Field name = stuClass.getDeclaredField("name");
        System.out.println("【获取指定属性】" + name);
    }

    /**
     * 获得方法
     */
    static void getMehtods() throws Exception {
        Class stuClass = Stu.class;
        System.out.println("【获取所有方法(包括Object putlic方法)】");
        Method[] declaredMethods = stuClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        System.out.println("【获取public方法】");
        Method[] methods = stuClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("【获取指定方法】");
        Method setName = stuClass.getDeclaredMethod("setName", String.class);
        System.out.println(setName);
    }

    /**
     * 获得构造器
     */
    static void getConstruct() throws Exception {
        Class stuClass = Stu.class;
        System.out.println("【获取所有构造器】");
        Constructor[] declaredConstructors = stuClass.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        System.out.println("【获取所有public构造器】");
        Constructor[] constructors = stuClass.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        System.out.println("【获取指定构造器】");
        Constructor declaredConstructor = stuClass.getDeclaredConstructor(int.class, String.class);
        System.out.println(declaredConstructor);
    }

    /**
     * 反射对性能有影响
     */
    static void wasteTime() throws Exception {
        /*******************正常获取属性消耗**********************/
        long startTime = System.currentTimeMillis();
        Stu stu = new Stu();
        for (int i = 0; i < 10_0000_0000; i++) {
            stu.getName();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("正常获取属性消耗:" + (endTime - startTime) + "ms");

        /*********************反射获取属性消耗********************/
        startTime = System.currentTimeMillis();
        Class<?> stuClass = Class.forName("com.fh.base.Stu");
        Method getName = stuClass.getDeclaredMethod("getName");
        stu = (Stu) stuClass.newInstance();
        for (int i = 0; i < 10_0000_0000; i++) {
            getName.invoke(stu);
        }
        endTime = System.currentTimeMillis();
        System.out.println("反射获取属性消耗:" + (endTime - startTime) + "ms");

        /*********************反射获取属性消耗********************/
        startTime = System.currentTimeMillis();
        getName.setAccessible(true);
        for (int i = 0; i < 10_0000_0000; i++) {
            getName.invoke(stu);
        }
        endTime = System.currentTimeMillis();
        System.out.println("反射获取属性消耗:" + (endTime - startTime) + "ms");
    }

    /**
     * 反射机制操作泛型
     *     泛型擦除机制引入泛型,java中的泛型仅仅是给编译器javac使用的,确保
     * 数据的安全性和免去强制类型转换问题。一旦编译完成,所有和泛型有关的类型
     * 全部被擦除。
     */
    static void getGeneric() throws Exception {
        Method method = Stu.class.getDeclaredMethod("getStu", List.class, Map.class);
        System.out.println("【获取方法中的所有泛型参数】");
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            System.out.println("***" + genericParameterType);
            if (genericParameterType instanceof ParameterizedType) {
                Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println("【获取泛型参数具体参数】" + actualTypeArgument);
                }
            }
        }

        method = Stu.class.getDeclaredMethod("getStu");
        Type genericReturnType = method.getGenericReturnType();
        if (genericReturnType instanceof ParameterizedType) {
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println("【获取泛型返回值的具体参数】" + actualTypeArgument);
            }
        }

    }


}

class Stu {
    private int id;
    private String name;
    private String sex;
    public String hobby;
    String schooh;

    private Stu(int id, String name, String sex) {
        this.id = id;
        this.name = name;
        this.sex = sex;
    }

    public Stu() {
    }

    public Stu(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public Map<String, Stu> getStu() {
        return null;
    }

    public void getStu(List<Stu> list, Map<String, Stu> map) {

    }

    public int getId() {
        return id;
    }

    public Stu setId(int id) {
        this.id = id;
        return this;
    }

    public String getName() {
        return name;
    }

    public Stu setName(String name) {
        this.name = name;
        return this;
    }

    public String getSex() {
        return sex;
    }

    public Stu setSex(String sex) {
        this.sex = sex;
        return this;
    }

    private void test1() {

    }

    @Override
    public String toString() {
        return "Stu{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", hobby='" + hobby + '\'' +
                ", schooh='" + schooh + '\'' +
                '}';
    }
}

 

测试2-通过反射设置表和类关系映射Annotation

package com.fh.gaoji.anotation;

import java.lang.annotation.*;
import java.lang.reflect.Field;

public class ClassAndTableYingSheTest {
    public static void main(String[] args) throws NoSuchFieldException {
        Class<Stu> stuClass = Stu.class;
        //获取类上的所有注解
        Annotation[] annotations = stuClass.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println("【获取Stu类所有注解】"+annotation);
        }
        //获取ClassAndTable注解
        ClassAndTable classAndTable = stuClass.getAnnotation(ClassAndTable.class);
        System.out.println("【获取指定类注解的值】"+classAndTable.value());

        System.out.println("【获取Stu类所有属性】");
        Field[] fields = stuClass.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field field =fields[i];
            FildAndColum annotation = field.getAnnotation(FildAndColum.class);
            System.out.println(annotation.name() + "***" +annotation.type() + "***" + annotation.length());

        }

        //获取FildAndColum注解
        Field field = stuClass.getDeclaredField("name");
        FildAndColum annotation = field.getAnnotation(FildAndColum.class);
        System.out.println("【获取指定类属性的值】"+annotation.name() + "***" +annotation.type() + "***" + annotation.length());


    }
}
@ClassAndTable("db_student")
class Stu{

    @FildAndColum(name = "db_id",type = "int",length = 10)
    private int id;

    @FildAndColum(name = "db_name",type = "varchar",length = 100)
    private String name;

    public int getId() {
        return id;
    }

    public Stu setId(int id) {
        this.id = id;
        return this;
    }

    public String getName() {
        return name;
    }

    public Stu setName(String name) {
        this.name = name;
        return this;
    }

    @Override
    public String toString() {
        return "Stu{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

/**
 * 类和【表】的映射
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface ClassAndTable{
    String value();//调用一个value属性时候,value可以省略,如 @MyAnnotation1("")
}

/**
 * 属性和【列】的映射
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FildAndColum{
    String name();
    String type();
    int length();
}

//@Target({ElementType.TYPE,ElementType.METHOD})
//@Retention(RetentionPolicy.RUNTIME)
//@interface MyAnnotation1{
//    //注解参数:参数类型+参数名()
//    String name() default "fh";//没有默认值,调用注解必须加上此参数!!!
//    int age() default 14;
//    String value();//调用一个value属性时候,value可以省略,如 @MyAnnotation1("")
//    String[] school() default {"AA","BB"};
//
//}

 

posted @ 2022-06-17 06:50  禁止摆烂  阅读(23)  评论(0)    收藏  举报