Java源码解析(2) —— Class(1)

Class —— 反射基石

  Java基本类之一,反射机制的基础。其意义为:类的抽象,即对“类”做描述:比如类有修饰、字段、方法等属性,有获得该类的所有方法、所有公有方法等方法。同时,Class也是Java类型中最重要的一种,表示原始类型(引用类型)及基本类型。

声明

1.Class的源码太长,这里分4部分解析,一些方法的实现源代码较长,这里就没有贴出来了,我会着重将叙述其作用,至于其实现逻辑,以本人现有水平估计也很难一一讲解清晰,大家姑且看之,若其中有错误地方或未讲解明白的可留言探讨。
2.阅读该文前,若对反射和泛型知识有一定基础最好。

源码

public final
    class Class implements java.io.Serializable,
                            java.lang.reflect.GenericDeclaration,
                              java.lang.reflect.Type,
                              java.lang.reflect.AnnotatedElement {
    private static final int ANNOTATION= 0x00002000;//注释类型
    private static final int ENUM      = 0x00004000;//枚举类型
    private static final int SYNTHETIC = 0x00001000;//合成类型,注0
    //枚举是一种类(class),注释是一种接口(interface)
    private transient String name;//全限定名(包+类名)
    private native String getName0();//本地方法获取name属性
    //注册本地方法
    private static native void registerNatives();
    static {
        registerNatives();
    }
    private Class() {}//唯一私有构造方法,说明Class不可由用户构造实例
    public String toString() {
        //这里重写toString,只区别了接口和Class
        return (isInterface() ? "interface " : (isPrimitive() ? "" : "class "))
            + getName();
    }
    //通过类全限定名获得该类(或接口)的Class对象(加载该类)
    @CallerSensitive   //注1
    public static Class forName(String className)
                throws ClassNotFoundException {
        Class caller = Reflection.getCallerClass();
        return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
    }
    @CallerSensitive
    public static Class forName(String name, boolean initialize,
                                   ClassLoader loader)
        throws ClassNotFoundException
    {
        //initialize : 是否立即初始化该类,注2
        //loader : 使用指定的类加载器加载
    }
    private static native Class forName0(String name, boolean initialize,
                                            ClassLoader loader,
                                            Class caller)
        throws ClassNotFoundException;
    //反射获得该类实例对象
 @CallerSensitive
    public T newInstance()
        throws InstantiationException, IllegalAccessException
    {
    //JDK明言:本方法在当前Java内存模型下不一定是正确的
        //反射获取该类实例对象,实例化对象不是通过new指令,而是直接
        //通过本地方法获取类的公有构造方法(无参),然后通过Constructor的
        //newInstance();方法实例化对象
        //这个过程还要检查是否有权限反射实例化该对象
    }
    //缓存上面方法已获取的公有构造方法,供下次使用
    private volatile transient Constructor cachedConstructor;
    //缓存调用本方法的最初对象的类Class对象,供安全检查使用,见注1
    private volatile transient Class       newInstanceCallerCache;
    //判断obj对象是否是该Class的实例
    public native boolean isInstance(Object obj);
    //判断cls是否是调用者同一类型或其子类类型
    public native boolean isAssignableFrom(Class cls);
    //判断该Class是否是接口类型
    public native boolean isInterface();
    //判断该Class是否是数组类型
    public native boolean isArray();
    //判断该Class是否是基本类型,注3(八大基本类型+一特殊基本类型)
    public native boolean isPrimitive();
    //判断该Class是否是注释类型
    public boolean isAnnotation() {
        return (getModifiers() & ANNOTATION) != 0;
    }
    //判断该Class是否是合成类型
    public boolean isSynthetic() {
        return (getModifiers() & SYNTHETIC) != 0;
    }
    public String getName() {
        String name = this.name;
        if (name == null)
            this.name = name = getName0();//通过本地方法获取全路径类名
        return name;
    }
    //获取加载该类的类加载器
    @CallerSensitive
    public ClassLoader getClassLoader() {
        ClassLoader cl = getClassLoader0();
        if (cl == null)
            return null;
        SecurityManager sm = System.getSecurityManager();//注5
        if (sm != null) {
            ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass());
        }
        return cl;
    }
    native ClassLoader getClassLoader0();
    //返回该类中变量字段的类型变量数组,按声明顺序排序,注4
    public TypeVariable>[] getTypeParameters() {
        if (getGenericSignature() != null)
            return (TypeVariable>[])getGenericInfo().getTypeParameters();
        else
            return (TypeVariable>[])new TypeVariable[0];
    }
    //获得该类的直接父类的Class对象,如果该类是接口,则返回null
    public native Class getSuperclass();
    //返回带参数化类型的直接父类的类型
    public Type getGenericSuperclass() {}
    //获取该类的包路径
    public Package getPackage() {
        return Package.getPackage(this);
    }
    //获取该类直接实现的所有接口
    public native Class[] getInterfaces();
    //获取所有接口,同上面的不同之处在于,若超接口是参数化类型(泛型)则返回的是其实际类型
    public Type[] getGenericInterfaces() {
        if (getGenericSignature() != null)
            return getGenericInfo().getSuperInterfaces();
        else
            return getInterfaces();
    }
    /**返回数组类型,若该类不是数组,返回null
     * 如:A[] a = new A[];
     * a.getClass().getComponentType()返回的是A类型(全路径名) 
     */
    public native Class getComponentType();
    //返回这个类的修饰符的对应的int值,二者可通过Modifier.toString()转换
    public native int getModifiers();
    //获取该类的所有签名(标记)列表
    public native Object[] getSigners();
    //设置该类的签名,注意方法修饰是默认,所以只有同包下类可用
    native void setSigners(Object[] signers);
    /**
     * 以上两个方法不是很懂具体用来干什么的,估计是和安全检查什么有关,因为
     * setSigners()是默认修饰,只能同包下访问(这就是说,用户是用不了的)
     */
}

注0:合成类型,参考:synthetic Java合成类型
注1:@CallerSensitive注解,参考:JVM注解@CallSensitive(HEL_WOR)
注2:类的初始化
  forName()方法默认是初始化类,不需要加载的的时候同时初始化类,需用forName的重载函数。类的加载、初始化可参考:Java类的加载
注3:Java基本数据类型
  除了8大基本类型,还有void,详见:Java变量数据类型
注4:Java类型,详见:Type Java类型。
注5:关于Java安全策略之安全管理器,现可以参考:java安全沙箱(四)(xionghuiCoder)

概述

  Class类,表示Java的基础类型(类+基本类型),是对Java类的抽象,描述的是类的信息,包括类的修饰符(public/private/protect/default/static/final等)、类的类型(一般类、枚举、注释、接口、数组等)、类的构造器、类的字段、类的方法等信息。所以在看待Class相关问题的时候应该从所有类的共性这个角度去看。注意,这里的类不是平常我们说的狭义上的类(class),而是广义上,包括了像接口、注释、数组等类型的类,下面若不特殊声明,类代表着广义上的类。
  每一个类在JVM内存中,有一个唯一的对应的Class对象,这个对象有着该类的描述信息,所以运行时可以通过该Class类对象进行相应的操作,这就是Java的反射了。(Java基本类型也对应一个Class对象)

//获得Class对象的方法
//1.通过 类型.class 获得,适用于所有类型
Class str = String.class;
Class i = int.class;
Class d = Double[].class;
//2.通过 Object的getClass() 方法获得,适用于所有非基本类型
A a = new A(); Class ac = a.getClass();
//3.通过 Class.forName(String name) 方法获得
Class ac1 = Class.forName("com.fcc.test.A");//注意要用全限定名

源码详解

1.forName
  静态方法,通过类的全限定名加载类,返回该类的Class对象,forName有两个重载,forName(String)和forName(String, boolean, ClassLoader),其中,第一个参数是类的全限定名,第二个参数是指加载该类的后是否初始化该类,默认是加载后并初始化该类,最后一个参数是指使用哪个类加载器加载该类,默认是使用当前类的类加载器加载该类。
2.newInstance
  创建该Class对象对应的对象实例,只有当类具有公有的无参构造方法才能成功,否则抛异常,关于newInstance详见:newInstance和new(编辑中)
3.getClassLoader
  获得加载该类的类加载器,在本JVM(Oracle HotSopt),当本类的类加载器是引导类加载器(bootStrap)则返回的是null。(类的加载见上面注2。)
4.getTypeParameters
  返回该类中声明(定义)的类变量数组,例如:

//关于TypeVariable详见注3
public class Main {
    public static void main(String[] args) throws Exception
    {
        Class cl = Main.class;
        TypeVariable[] types = cl.getTypeParameters();
        for(TypeVariable type : types){
            System.out.println(type.getName());
        }
    }
}
K
V

5.getSuperclass
  获得该Class的直接父类对应的Class对象,如果该Class是基本类型(包括void,注意是小写的关键字void,不是大写的类Void)、接口、注释,则返回null。

Class c0 = Main.class;//类,返回直接父类,泛型当做普通类处理
Class c1 = EnumA.class;//枚举类型,默认继承Enum类
Class c2 = int.class;//基本类型返回null
Class c3 = int[].class;//数组统一返回 class Object
Class c4 = InterfaceB.class;//接口也是返回null
Class c5 = Deprecated.class;//注释类型也返回null,c5.isInterface() 为true
System.out.println("类 : " + c0.getSuperclass());
System.out.println("枚举 : " + c1.getSuperclass());
System.out.println("基本类型 : " + c2.getSuperclass());
System.out.println("数组 : " + c3.getSuperclass());
System.out.println("接口 : " + c4.getSuperclass());
System.out.println("注释 : " + c5.getSuperclass());
//输出结果
类 : class java.lang.Object
枚举 : class java.lang.Enum
基本类型 : null
数组 : class java.lang.Object
接口 : null
注释 : null

6.getGenericSuperclass
  获得直接父类的类型,可以理解为在5的基础上,如果其是泛型,再获得其类型原型(但需要继承时显式表示)。

public class Main<K, V> {
    public static void main(String[] args) throws Exception
    {
        Class c0 = ClassA.class;
        Class c1 = EnumA.class;//枚举类型,默认继承Enum类
        Class c2 = int.class;//基本类型返回null
        Class c3 = ClassA[].class;//数组统一返回 class Object
        Class c4 = InterfaceB.class;//接口也是返回null
        Class c5 = Deprecated.class;//注释类型也返回null
        System.out.println("类 : " + c0.getGenericSuperclass());
        System.out.println("枚举 : " + c1.getGenericSuperclass());
        System.out.println("基本类型 : " + c2.getGenericSuperclass());
        System.out.println("数组 : " + c3.getGenericSuperclass());
        System.out.println("接口 : " + c4.getGenericSuperclass());
        System.out.println("注释 : " + c5.getGenericSuperclass());
        System.out.println(c2.isInterface());
    }
}
class ClassA<K,V> extends Main<K,V>{}//注1
//输出结果
类 : com.fcc.test.Main
枚举 : java.lang.Enum
基本类型 : null
数组 : class java.lang.Object
接口 : null
注释 : null1:如果是以下形式
class ClassA extends Main{}
则输出为:类 : com.fcc.test.Main

7.getInterfaces
8.getGenericInterfaces
  getInterfaces/getGenericInterfaces这一对同getSuperclass/getGenericSuperclass类似,getInterfaces/getGenericInterfaces前者是获得该类直接实现的所有接口(不包括接口的父接口,也不包括父类实现的接口),后者是,如果接口是泛型,还原泛型的原型(但需要实现时显式表示,这一点同getGenericSuperclass类似)。不过不管是哪一对,要注意,返回值类型的不同。

Class c0 = ClassB.class;
Class[] ifaces = c0.getInterfaces();
for(Class c : ifaces){
    System.out.println(c);
}
Type[] ifaces1 = c0.getGenericInterfaces();
for(Type c : ifaces1){
    System.out.println(c);
}
class ClassB<E> extends ClassA implements InterfaceB<E>{}
//输出结果
interface com.fcc.test.InterfaceB
com.fcc.test.InterfaceB<E>

你可能感兴趣的:(Java源码解析,Java源码解析)