美文网首页
Class、Constructor、Method、Field等继

Class、Constructor、Method、Field等继

作者: sollian | 来源:发表于2018-06-05 17:32 被阅读25次
Class、Method、Field等继承体系图

源码基于android api27。

Type

public interface Type {
    /**
     * Returns a string describing this type, including information
     * about any type parameters.
     *
     * @implSpec The default implementation calls {@code toString}.
     *
     * @return a string describing this type
     * @since 1.8
     * @hide Pending tests
     */
    default String getTypeName() {
        return toString();
    }
}

Type是所有类型的父接口,主要用于反射。关于讲解,可以参见:Java中的Type详解

AnnotatedElement

public interface AnnotatedElement {
    default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
        return getAnnotation(annotationClass) != null;
    }

    <T extends Annotation> T getAnnotation(Class<T> annotationClass);

    Annotation[] getAnnotations();

    default <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
        return AnnotatedElements.getDirectOrIndirectAnnotationsByType(this, annotationClass);
    }


    default <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
        Objects.requireNonNull(annotationClass);
        // Loop over all directly-present annotations looking for a matching one
        for (Annotation annotation : getDeclaredAnnotations()) {
            if (annotationClass.equals(annotation.annotationType())) {
                // More robust to do a dynamic cast at runtime instead
                // of compile-time only.
                return annotationClass.cast(annotation);
            }
        }
        return null;
    }

    default <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
        return AnnotatedElements.getDirectOrIndirectAnnotationsByType(this, annotationClass);
    }

    Annotation[] getDeclaredAnnotations();

提供了用来获取注解的方法。

GenericDeclaration

public interface GenericDeclaration extends AnnotatedElement {
    //用于获取泛型参数
    public TypeVariable<?>[] getTypeParameters();
}

泛型声明接口,表示用到了泛型。

Member

public interface Member {
    //标识所有访问修饰符为public的成员,包括父类继承的
    public static final int PUBLIC = 0;
    //标识所有当前类的成员
    public static final int DECLARED = 1;

    //获取该成员所在的类
    public Class<?> getDeclaringClass();

    //获取该成员的名称
    public String getName();

    //获取该成员的所有修饰符,整数值每一位代表一个修饰符
    public int getModifiers();

    //判断该成员是否是编译器生成的。
    public boolean isSynthetic();

关于修饰符的解读,可以使用Modifier类。
关于isSynthetic的理解,可以参考Java的synthetic修饰词

AccessibleObject

该类是Field、Method、Constructor对象的基类,提供了在使用反射对象时,取消Java语言默认访问控制检查的能力。在使用Field、Method、Constructor执行反射操作时,会执行访问控制检查(主要是public、protected、private和默认访问权限的检查,也包括final)。

主要方法有:

    //设置是否取消Java语言默认访问控制检查
    public void setAccessible(boolean flag) throws SecurityException {
        setAccessible0(this, flag);
    }

    public boolean isAccessible() {
        return override;
    }

比如:

public class JavaDemo {
    private int value = 1;

    public int getValue() {
        return value;
    }

    public static void main(String[] args) {
        try {
            Class c = JavaDemo.class;
            Object obj = c.newInstance();
            Field f = c.getDeclaredField("value");
            //f.setAccessible(true);
            f.setInt(obj, 5);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

如上,若value有final修饰,则会抛出IllegalAccessException,需要打开注释行才不会抛出异常。

那么问题来了,反射真的可以修改final修饰的字段的值么?可以参考 Java反射机制可以动态修改实例中final修饰的成员变量吗?

Executable

Method和Constructor的父类,简要看一下public方法:

    //获取所有参数的Class类型,若包含泛型,有上限则返回其上限,否则返回Object.class。
    //如:K extends Integer,返回Integer.class。
    public abstract Class<?>[] getParameterTypes();

    //获取参数数量
    public int getParameterCount() {
        throw new AbstractMethodError();
    }

    //获取参数的Type类型
    public Type[] getGenericParameterTypes() {
        return Types.getTypeArray(getMethodOrConstructorGenericInfoInternal().genericParameterTypes, false);
    }

    //返回Parameter数组,可以获取更加细致的信息
    public Parameter[] getParameters() {
        return privateGetParameters().clone();
    }

    //获取所有抛出的异常
    public abstract Class<?>[] getExceptionTypes();

    public Type[] getGenericExceptionTypes() {
        return Types.getTypeArray(getMethodOrConstructorGenericInfoInternal().genericExceptionTypes, false);
    }

    //判断是否包含可变参数
    public boolean isVarArgs()  {
        return (accessFlags & Modifier.VARARGS) != 0;
    }

关于方法的获取,举几个例子:

public class JavaDemo<K extends Integer, M> {

    public void test1(K age, M name) {
    }

    public void test2(String... urls) {//包含可变参数
    }

    public static void main(String[] args) {
        try {
            Class c = JavaDemo.class;
            Method test1 = c.getDeclaredMethod("test1", Integer.class, Object.class);
            Method test2 = c.getDeclaredMethod("test2", int.class, String[].class);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

相关文章

网友评论

      本文标题:Class、Constructor、Method、Field等继

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