菜菜

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Class主要封装对Class对象的操作。Class类实现Serializable,GenericDeclaration,Type,AnnotatedElement接口。

GenericDeclaration : 所有声明类型变量实体的通用接口

 

Type: Java所有类型的父接口,它包含原始类型,参数化类型,数组类型,类型变量,原始类型.

 

注意参数化类型和类型变量的区别.

  1:A TypeVariable refers to the declaration of the type variable

  2:a ParametrizedType is a use of such a type

注意下面这个代码

public class View
{
    public Collection<String> c;

    public static void main(String[] args) throws NoSuchFieldException, SecurityException
    {
        System.out.println(Collection.class.getTypeParameters()[0]); // E
        System.out.println(Collection.class.getTypeParameters()[0] instanceof TypeVariable); // true
        System.out.println(Collection.class.getTypeParameters()[0] instanceof ParameterizedType); // false
        Field field = View.class.getField("c");
        System.out.println(field.getGenericType()); // java.util.Collection<java.lang.String>
        System.out.println(field.getGenericType() instanceof TypeVariable); // false
        System.out.println(field.getGenericType() instanceof ParameterizedType); // true
    }

    public static class T<O>
    {
        O o;
    }

}

T newInstance()生成对应Class的实例,使用无参构造函数生成实例,注意下面这个代码。

@CallerSensitive
    public T newInstance()
        throws InstantiationException, IllegalAccessException
    {
        if (System.getSecurityManager() != null) {
            checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
        }

        // NOTE: the following code may not be strictly correct under
        // the current Java memory model.

        // Constructor lookup
        if (cachedConstructor == null) {
            if (this == Class.class) {
                throw new IllegalAccessException(
                    "Can not call newInstance() on the Class for java.lang.Class"
                );
            }
            try {
                Class<?>[] empty = {};
                final Constructor<T> c = getConstructor0(empty, Member.DECLARED);
                // Disable accessibility checks on the constructor
                // since we have to do the security check here anyway
                // (the stack depth is wrong for the Constructor's
                // security check to work)
                java.security.AccessController.doPrivileged(
                    new java.security.PrivilegedAction<Void>() {
                        public Void run() {
                                c.setAccessible(true);
                                return null;
                            }
                        });
                cachedConstructor = c;
            } catch (NoSuchMethodException e) {
                throw (InstantiationException)
                    new InstantiationException(getName()).initCause(e);
            }
        }
        Constructor<T> tmpConstructor = cachedConstructor;
        // Security check (same as in java.lang.reflect.Constructor)
        int modifiers = tmpConstructor.getModifiers();
        if (!Reflection.quickCheckMemberAccess(this, modifiers)) {
            Class<?> caller = Reflection.getCallerClass();
            if (newInstanceCallerCache != caller) {
                Reflection.ensureMemberAccess(caller, this, null, modifiers);
                newInstanceCallerCache = caller;
            }
        }
        // Run constructor
        try {
            return tmpConstructor.newInstance((Object[])null);
        } catch (InvocationTargetException e) {
            Unsafe.getUnsafe().throwException(e.getTargetException());
            // Not reached
            return null;
        }
    }

使用了一个cachedConstructor,并且这个属性是volatile属性。意思就是Class对象会缓存一个构造器,免得每次调用都去解析构造器。 

newInstanceCallerCache 用于保存校验调用者权限缓存。如果caller没有改变,不用在用校验权限.

 

Class类型isXXX方法的实现都是检查类的字节码格式,具体可以查看Java8的虚拟机规范定义的类文件格式.比如像这种

public boolean isAnnotation() {
        return (getModifiers() & ANNOTATION) != 0;
    }

 

getName()方法。也有一个缓存的name,防止每次都要调用虚拟机接口.

   public String getName() {
        String name = this.name;
        if (name == null)
            this.name = name = getName0();
        return name;
    }
Element Type           Encoding
boolean                 Z
byte                    B
char                    C
class or interface     Lclassname;
double                  D
float                   F
int                     I
long                    J
short                   S
The class or interface name classname is the binary name of the class specified above.

Examples:

 String.class.getName()
     returns "java.lang.String"
 byte.class.getName()
     returns "byte"
 (new Object[3]).getClass().getName()
     returns "[Ljava.lang.Object;"
 (new int[3][4][5][6][7][8][9]).getClass().getName()
     returns "[[[[[[[I"
 

这个方法返回的是类的二进制名称。

 

2. getClassLoader 返回此类的加载器,如果是启动类加载上来的,返回null.基本类型和Void都是返回null。

 

 

3. getDeclaredXXX返回类所有声明的,getXXXX基本上只返回public的。

 

4. getResourceAsStream 因为由启动类加载的类没有类加载器,委托给系统类加载器。参数的参数如果是绝对地址,不处理,如果不是绝对地址,那么就是当前包/resourceName

 

5.为了加快速度,getXXX,getDeclaredXX会从缓存中获取.

// Caches for certain reflective results
    private static boolean useCaches = true;

    // reflection data that might get invalidated when JVM TI RedefineClasses() is called
    private static class ReflectionData<T> {
        volatile Field[] declaredFields;
        volatile Field[] publicFields;
        volatile Method[] declaredMethods;
        volatile Method[] publicMethods;
        volatile Constructor<T>[] declaredConstructors;
        volatile Constructor<T>[] publicConstructors;
        // Intermediate results for getFields and getMethods
        volatile Field[] declaredPublicFields;
        volatile Method[] declaredPublicMethods;
        volatile Class<?>[] interfaces;

        // Value of classRedefinedCount when we created this ReflectionData instance
        final int redefinedCount;

        ReflectionData(int redefinedCount) {
            this.redefinedCount = redefinedCount;
        }
    }

 

可以通过此系统变量来关闭反射缓存。

sun.reflect.noCaches

 

 

posted on 2019-07-09 17:04  好吧,就是菜菜  阅读(463)  评论(0编辑  收藏  举报