美文网首页
注解&反射

注解&反射

作者: ttyttytty | 来源:发表于2021-04-08 23:20 被阅读0次

注解

  • 形式:关键字:@interface
  • when:@Retention(RetentionPolicy.RUNTIME)
  • where:@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
public @interface AnnotationPerson {
    String value() default "ty";
}

重点是结合反射,处理注解的逻辑

  public void processAnnotation() {
        Class<? extends Person> aClass = this.getClass();
        Annotation[] annotations = aClass.getAnnotations();
        if (annotations != null && annotations.length > 0) {
            for (Annotation annotation : annotations) {
                if (annotation instanceof AnnotationPerson) {
                    System.out.println("class AnnotationPerson");
                }
            }
        }

        Field[] fields = aClass.getDeclaredFields(); // 本类声明的所有字段
        for (Field field : fields) {
            Annotation[] fieldAnnotations = field.getAnnotations();
            if (fieldAnnotations != null && fieldAnnotations.length > 0) {
                for (Annotation fieldAnnotation : fieldAnnotations) {
                    if (fieldAnnotation instanceof AnnotationPerson) {
                        System.out.println("field AnnotationPerson " + field);
                        try {
                            field.setAccessible(true);
//                            field.set(this, 1);// age is int but not default string ty
                           field.set(this, ((AnnotationPerson) fieldAnnotation).value());
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                }

            }
        }
        System.out.println(this.toString());
    }

反射

  • 反射:提供的是runtime阶段获取类的class实例、方法、属性、注解,并且能够调用类的方法的途径,这种动态获取类信息和调用类方法的机制被称之为反射。(正常场景下,java从源码到运行有3个阶段:source class runtime)

Type

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

public class TypeTest<T extends Number & Serializable, V> {
    private Map<String, TypeTest> map;
    private Set<String> set1;
    private Class<?> clz;
    private Holder<String> holderStr;
    private Holder holder;   //未指定具体类型,非泛型参数,是class
    private List<String> list;   //获取到泛型类型class java.lang.String
    private ArrayList<String> arrayList;
    private Map.Entry<String, String> entry;

    public String str;
    private Integer i;
    private Set set;  //没给与泛型,它不会是ParameterizedType参数化类型
    private List aList;   //没给与泛型,它不会是ParameterizedType参数化类型
    private List<? extends Number> listUpper;
    private List<? super String> listLower;

    private Map<? extends String, ? super Number> map1;
    private Map<? extends String, ?> map2;

    private Class<?> clazz;


    private T key;
    private V value;
    // 显然它本身是个GenericArrayType类型,里面是TypeVariable类型
    private V[] values;
    //ParameterizedType 和 TypeVariable的结合
    private List<T> tList;

    static class Holder<V> {
    }

    public static void main(String[] args) {
        getAllTypeTest();
        getParameterizedTypeField();
    }

    // 这里面有各种各样的数组:各有不同 方便看测试效果
    // 含有泛型数组的才是GenericArrayType
    public void allTypeMethod(List<String>[] pTypeArray,             //GenericArrayType  =数组+泛型(如是list,需指定具体类型),否则是class
                              List<TypeTest>[] g,        //GenericArrayType
                              List[] listarray,                      //class
                              T[] vTypeArray,                        //GenericArrayType

                              List listwithnot,                      //class
                              List<String> list,                     //ParameterizedType  =泛型;例如:List< T>、Map< K,V>等带有参数化的对象,需指定具体类型,否则是class
                              List<? extends Number> wildcardList,   //ParameterizedType

                              String[] strings,                      //class
                              TypeTest[] test            //class
    ) {
    }


    public static void getAllTypeTest() {
        System.out.println("***************************************getAllTypeTest***********************************************");
        Method[] declaredMethods = TypeTest.class.getDeclaredMethods();
        for (Method method : declaredMethods) {
            if (!method.getName().equalsIgnoreCase("allTypeMethod")) {
                continue;
            }
            System.out.println("declare Method:" + method); //declare Method:public void com.fsx.maintest.GenericArrayTypeTest.testGenericArrayType(java.util.List[],java.lang.Object[],java.util.List,java.lang.String[],com.fsx.maintest.GenericArrayTypeTest[])
            Type[] types = method.getGenericParameterTypes();
            tellConcreteType(types);
        }
    }

    public static void getParameterizedTypeField() {
        System.out.println("***************************************getParameterizedTypeField***********************************************");
        Field field = null;
        try {
            Field[] fields = TypeTest.class.getDeclaredFields();
//            Field[] fields = GenericArrayTypeTest.class.getFields();
            Type[] types = new Type[fields.length];
            for (int i = 0; i < fields.length; i++) {
                field = fields[i];
                types[i] = field.getGenericType();
            }
            tellConcreteType(types);
        } catch (Exception ignored) {
        }
    }

    private static void tellConcreteType(Type[] types) {
        for (Type type : types) {
            System.out.println("type = " + type);
            if (type instanceof ParameterizedType) {//泛型;例如:List< T>、Map< K,V>等带有参数化的对象,需指定具体类型,否则是class
                ParameterizedType parameterizedType = (ParameterizedType) type;
                System.out.println("\tParameterizedType type :" + parameterizedType);
                System.out.println("\tParameterizedType ActualTypeArguments :" + Arrays.asList(parameterizedType.getActualTypeArguments()));
                System.out.println("\tParameterizedType RawType :" + parameterizedType.getRawType());
                System.out.println("\tParameterizedType OwnerType :" + parameterizedType.getOwnerType());
                for (Type item : parameterizedType.getActualTypeArguments()) {
                    //参数化类型可能有多个
                    System.out.println("\t  获取到getActualTypeArguments为:" + item);
                    if (item instanceof WildcardType) {
                        printWildcardType((WildcardType) item);
                    }
                    if (item instanceof TypeVariable) {
                        TypeVariable typeVariable = (TypeVariable) item;
                        printTypeVariable(typeVariable);
                    }
                }
            } else if (type instanceof GenericArrayType) {//=数组+泛型(如是list,需指定具体类型),否则是class
                GenericArrayType genericArrayType = (GenericArrayType) type;
                System.out.println("\tGenericArrayType type :" + genericArrayType);
                Type genericComponentType = genericArrayType.getGenericComponentType();
                System.out.println("\t\tgenericComponentType:" + genericComponentType);
                if (genericComponentType instanceof WildcardType) {
                    printWildcardType((WildcardType) genericComponentType);
                }
                if (genericComponentType instanceof TypeVariable) {
                    TypeVariable typeVariable = (TypeVariable) genericComponentType;
                    printTypeVariable(typeVariable);
                }
            } else if (type instanceof WildcardType) {//通配符表达式,但并不是Java类型中的一种,表示的仅仅是类似 ? extends T、? super K这样的通配符表达式。
                WildcardType wildcardType = (WildcardType) type;
                System.out.println("\tWildcardType type :" + wildcardType);
            } else if (type instanceof TypeVariable) {
                TypeVariable typeVariable = (TypeVariable) type;
                System.out.println("\tTypeVariable type :" + typeVariable);
            } else {
                Class clazz = (Class) type;
                System.out.println("\tClass :" + clazz);
            }
        }
    }

    private static void printWildcardType(WildcardType wildcardType) {
        for (Type type : wildcardType.getUpperBounds()) {
            System.out.println("\t\t上界:" + type);
        }
        for (Type type : wildcardType.getLowerBounds()) {
            System.out.println("\t\t下界:" + type);
        }
    }

    private static void printTypeVariable(TypeVariable typeVariable) {
        for (Type type : typeVariable.getBounds()) {
            System.out.println("\t\t" + ": TypeVariable getBounds " + type);
        }
        System.out.println("\t\t定义Class getGenericDeclaration: " + typeVariable.getGenericDeclaration());
        System.out.println("\t\tgetName: " + typeVariable.getName());
    }
}

代码

  • Class类型:类在加载的时候,会需要一个描述类本身信息(有哪些字段,构造函数,注解等等)的一个类,可以理解为类类型。
  • 如何获取一个类的类类型?如何获取Field/constructor/annotation……
    https://www.codenong.com/cs106053250/
Field tmpField = metadata.getClass().getDeclaredField(field.getFieldName());
            tmpField.setAccessible(true);
            Type type = tmpField.getType();
            if (null != type) {
                if (type.equals(String.class)) {
                    Object objTmp = tmpField.get(metadata);
                    if (null != objTmp) {
                        result.add(objTmp.toString());
                    }
                } else if (type.equals(List.class)) {
                    Type genericType = tmpField.getGenericType();
                    if (genericType instanceof ParameterizedType) {
                        ParameterizedType pt = (ParameterizedType) genericType;
                        Type[] subTypes = pt.getActualTypeArguments();
                        if (null != subTypes) {
                            Class<?> genericClazz = (Class<?>) subTypes[0];
                            if (genericClazz.equals(String.class)) {
                                result = (List<String>) tmpField.get(metadata);
                            }
                        }
                    }
                }
            }
                        // 如果类型是Double
                if (field.getGenericType().toString().equals(
                        "class java.lang.Double")) {
                    Method m = (Method) object.getClass().getMethod(
                            "get" + getMethodName(field.getName()));
                    Double val = (Double) m.invoke(object);
                    if (val != null) {
                        System.out.println("Double type:" + val);
                    }
 
                }

反射使用场景(结合注解使用)

1.获取配置(字段信息)

  • 数据的读写权限码
  • 如何处理字段修改名字->字段注解@HiResearchField的name字段,不处理的字段也要记得使用默认的字段名
  • 处理字段的类型(反射getMetadataSerializeField)
  • 数据重复上传覆盖(metadata.setUniqieId() + @HiResearchRemoveDuplication)
    2.调用通用的方法
  • execQuery接口,仅输入的配置不同
    3.封装对象
  • 从sampleSet中,根据每个字段的码(int or string)(map的key,提取value)
    4.AOP
    https://www.cnblogs.com/niujifei/p/12313684.html
    https://juejin.cn/post/6844903905483030536

相关文章

网友评论

      本文标题:注解&反射

      本文链接:https://www.haomeiwen.com/subject/rhybkltx.html