java基础之反射


前言

时间多少不是努力的标准,而是你是否纠正了错误,提高了水平。没有进步,那只是单纯的浪费时间,别感动了自己

java的反射还是得会一点的


一、什么是反射?

Oracle 官方对反射的解释是:

Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to usereflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions. The API accommodates applications that need access to either the public members of a target object (based on its runtime class) or the members declared by a given class. It also allows programs to suppress default reflective access control.

总结就是:通过反射,我们可以在运行时获得程序或程序集中每一个类型的成员和成员的信息


二、反射的API 规范

下图来自于oracle官网

CLass类并不在这里,它属于java.lang包,不属于java.lang.reflect.


三、反射API使用示例

AnnotatedElement

Represents an annotated element of the program currently running in this VM.
即表示带注解的元素
这是一个接口,ClassConstructorFieldMethodParameter自然是实现了该接口,此外还有PackageTypeVariable

	// 是否被入参的注解标注
	boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
   	// 获取注解对象
    <T extends Annotation> T getAnnotation(Class<T> annotationClass);
    // 获取该元素上的所有注解
    Annotation[] getAnnotations();
	// 返回与此元素关联的注释.此方法与getAnnotation()的区别在于,此方法检测其参数是否为可重复注解类型
	<T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass)
	//  如果直接存在这样的注解(是直接),则返回此元素对指定类型的注释,否则返回 null
	<T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass)
	//  如果直接存在这样的注解(是直接),则返回此元素对指定类型的注解,否则返回 null,此方法检测其参数是否为可重复注解类型
	<T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass)
	//获取所有直接标注在该元素上的注解
 	Annotation[] getDeclaredAnnotations()

下面是例子

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Name {
    String value();
}
@Name("parent")
class  TestParent{

}
public class Test  extends TestParent {
    public static void main(String[] args) {
        Class<Test> testClass = Test.class;

        System.out.println(testClass.isAnnotationPresent(Name.class)); // true

        System.out.println(testClass.getAnnotation(Name.class)); //@Name(value=parent)

        System.out.println(Arrays.toString(testClass.getAnnotations())); // [@Name(value=parent)]

        System.out.println(Arrays.toString(testClass.getAnnotationsByType(Name.class))); // [@Name(value=parent)]

        System.out.println(testClass.getDeclaredAnnotation(Name.class));  // null

        System.out.println(Arrays.toString(testClass.getDeclaredAnnotationsByType(Name.class)));  // []

        System.out.println(Arrays.toString(testClass.getDeclaredAnnotations())); //[]
    }
}


Type

Type 是 Java 编程语言中所有类型的父接口,GenericArrayTypeParameterizedTypeTypeVariableWildcardType是它的子接口,当然Class类也实现了它。
它只有一个方法

	// 返回描述此类型的字符串,包括有关任何类型参数的信息。
	String getTypeName()

Member

成员是表示单个成员(字段或方法)或构造函数的标识信息的接口。其实现主要有3个,FieldMethodConstructor

	// 获取当前成员是在哪个Class中声明的
	Class<?> getDeclaringClass();
	// 获取成员名称
	String getName();
	// 获取成员的访问标识(public,private...)
	int getModifiers();
	// 如果该成员是由编译器引入的,则返回true
	boolean isSynthetic()

使用示例

interface SuperClass<T> {
    T method(T param);
}
public class Test implements SuperClass<String> {

    @Override
    public String method(String param) {
        return "hello";
    }

    public static void main(String[] args) throws Exception{
        Class<Test> clazz = Test.class;
        Method[] methods = clazz.getDeclaredMethods();
        System.out.println(methods.length); // 3

        Method method = clazz.getMethod("method", Object.class);
        System.out.println(method.getDeclaringClass()); // class Test
        System.out.println(Modifier.isPublic(method.getModifiers())); // true
        System.out.println(method.isSynthetic()); // true
    }
}

使用javap命令查看Test类的成员,可以看到相比源代码,多出了一个方法,这是由编译器生成的。(兼容低版本)
javap


GenericDeclaration

声明类型变量的所有实体的通用接口,继承自AnnotatedElement,说明它有获取注解信息的能力

public interface GenericDeclaration extends AnnotatedElement {
  	// 获取类型变量  
    public TypeVariable<?>[] getTypeParameters();
}

它只有四个实现,也只有这四个实现可以获取类型参数
在这里插入图片描述


ParameterizedType、GenericArrayType、TypeVariable、WildcardType以及Class

这5个Type子接口或者实现构成了java语言层面的类型。

ParameterizedType

ParameterizedType表示参数化类型

	// 获取实际类型参数
	Type[] getActualTypeArguments();
	// 获取声明此类型的类或接口的Type对象。
	Type getRawType();
	// 获取该类型所属的类型
	Type getOwnerType();

看注释应该是一脸懵逼的,还是看例子吧。

	public class Test {

    public static <U> void method(Map.Entry<String,U> mapEntry){

    }
    public static void main(String[] args) throws Exception{
        Method method = Test.class.getDeclaredMethod("method",Map.Entry.class);
        Type genericType = method.getGenericParameterTypes()[0];
        System.out.println(genericType instanceof ParameterizedType); // true
        ParameterizedType parameterizedType = (ParameterizedType) genericType;
        System.out.println(parameterizedType.getRawType()); // interface java.util.Map$Entry
        System.out.println(Arrays.toString(parameterizedType.getActualTypeArguments())); // [class java.lang.String, U]
        System.out.println(parameterizedType.getOwnerType()); // interface java.util.Map
    }
}

GenericArrayType

GenericArrayType表示泛型数组类型

public interface GenericArrayType extends Type {
   	// 获取数组元素类型
    Type getGenericComponentType();
}

例子

public class Test<T> {

    private T[] objs;

    public static void main(String[] args) throws Exception{
        Field objs = Test.class.getDeclaredField("objs");
        System.out.println(objs.getType()); // class [Ljava.lang.Object;
        Type genericType = objs.getGenericType();
        System.out.println(genericType instanceof GenericArrayType); //true

        GenericArrayType genericArrayType = (GenericArrayType) genericType;
        System.out.println(genericArrayType.getGenericComponentType().getClass()); // class sun.reflect.generics.reflectiveObjects.TypeVariableImpl
        System.out.println(genericArrayType.getGenericComponentType().getTypeName()); // T
    }
}

TypeVariable

它继承了AnnotatedElement,表明了它可以被注解标注

public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
  	// 获取表示此类型变量上限的Type对象数组
    Type[] getBounds();
	// 获取泛型声明者(不太会形容,下面有例子)
    D getGenericDeclaration();
	// 获取名字(泛型变量都有名字,如Map的KV)
    String getName();
	// 获取表示此类型变量上限的AnnotatedType对象数组
     AnnotatedType[] getAnnotatedBounds();
}

例子

public class Test<@Test.Anno("TYPE_PARAMETER") T extends @Test.Anno("TYPE_USE") CharSequence & Closeable > {

    @Target({ElementType.TYPE_PARAMETER,ElementType.TYPE_USE})
    @Retention(RetentionPolicy.RUNTIME)
    @interface Anno{
       String  value();
    }

    public static void main(String[] args) throws Exception{
        TypeVariable<Class<Test>>[] typeParameters = Test.class.getTypeParameters();
        System.out.println(typeParameters.length); // 1
        TypeVariable<Class<Test>> typeParameter = typeParameters[0];
        System.out.println(typeParameter.getGenericDeclaration()); // class Test
        for (Annotation annotation : typeParameter.getAnnotations()) {
            System.out.println(annotation); // @Test$Anno(value=TYPE_PARAMETER)
        }
        Type[] bounds = typeParameter.getBounds();
        System.out.println(Arrays.toString(bounds)); //  [interface java.lang.CharSequence, interface java.io.Closeable]
        AnnotatedType[] annotatedBounds = typeParameter.getAnnotatedBounds();
        for (AnnotatedType annotatedBound : annotatedBounds) {
            for (Annotation annotation : annotatedBound.getAnnotations()) {
                System.out.println(annotation); // @Test$Anno(value=TYPE_USE)
            }
        }
    }
}

WildcardType

WildcardType 表示通配符类型表达式

源码

public interface WildcardType extends Type {
    
    // 获取上界
    Type[] getUpperBounds();
	// 获取下界
    Type[] getLowerBounds();
}

例子

public class Test {

    public void test(List<? extends CharSequence> a, Comparator<? super Cloneable> comparator){}
    public static void main(String[] args) throws Exception{
        Method method = Test.class.getMethod("test",List.class,Comparator.class);
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for (Type genericParameterType : genericParameterTypes) {
            ParameterizedType parameterizedType = (ParameterizedType) genericParameterType;
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println(actualTypeArgument instanceof WildcardType); //true true
                assert actualTypeArgument instanceof WildcardType;
                WildcardType type = (WildcardType) actualTypeArgument;
                System.out.println(Arrays.toString(type.getLowerBounds())); // []  [interface java.lang.Cloneable]
                System.out.println(Arrays.toString(type.getUpperBounds())); // [interface java.lang.CharSequence]   [class java.lang.Object]
                System.out.println(type); // ? extends java.lang.CharSequence    ? super java.lang.Cloneable
            }
        }
    }
}

AnnotatedParameterizedType

AnnotatedParameterizedType表示参数化类型的潜在注释使用,其类型参数本身可能表示类型的注释使用

public interface AnnotatedParameterizedType extends AnnotatedType {
	// 返回此参数化类型的潜在注释实际类型参数
    AnnotatedType[] getAnnotatedActualTypeArguments();
}


public class Test extends @Ann("map") HashMap<@Ann("str") String, @Ann("obj") Object> {

    public static void main(String[] args) throws Exception {
        AnnotatedType annotatedSuperclass = Test.class.getAnnotatedSuperclass();
        AnnotatedParameterizedType type = (AnnotatedParameterizedType) annotatedSuperclass;
        System.out.println(type.getType()); // java.util.HashMap<java.lang.String, java.lang.Object>
        System.out.println(type.getAnnotation(Ann.class)); // @Ann(value=map)
        AnnotatedType[] annotatedActualTypeArguments = type.getAnnotatedActualTypeArguments();
        for (AnnotatedType annotatedActualTypeArgument : annotatedActualTypeArguments) {
            System.out.println(annotatedActualTypeArgument.getType()); // class java.lang.String class java.lang.Object
            System.out.println(annotatedActualTypeArgument.getAnnotation(Ann.class)); // @Ann(value=str) @Ann(value=obj)
        }
    }
}

总结

这篇博客对反射相关的API做了比较详细的介绍,反射的使用在框架中到处都是,我们没有理由不学习。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值