注解
- 形式:关键字:@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
- GenericArrayType ParameterizedType WildcardType TypeVariable Class类型
[https://cloud.tencent.com/developer/article/1497707]
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
网友评论