jdk源码之Class

jdk源码之Class

一、类图

在这里插入图片描述

二、是什么

  1. Class对象的由来是将.class文件读入内存,并为之创建一个Class对象。
  2. Class类的实例表示正在运行的java应用程序中的类和接口。枚举是一种类,注解是一种接口。每个数组被映射为Class对象的一个类,所有具有相同元素类型和维数的数组都共享该Class对象。基本的java类型和关键字void也表示为Class对象。
    Class 类没有公共的构造方法。Class对象是在加载类时由java虚拟机调用类加载器中的defineClass方法自动构造的。
  3. 在运行期间,一个类,只有一个Class对象产生。

三、构造方法

    private Class(ClassLoader loader) {
        // Initialize final field for classLoader.  The initialization value of non-null
        // prevents future JIT optimizations from assuming this final field is null.
        classLoader = loader;
    }

只有一个构造方法,私有的。仅Java虚拟机创建Class对象。

四、获取实例

三种方式
1.运用.class和.TYPE

// 普通类获取Class的实例。接口,枚举,注解,都可以通过这样的方式进行获得Class实例
Class<Stuent> mainClass = Stuent.class;

// 基本类型和封装类型获得Class实例的方式,两者等效的。
Class<Integer> integerClass = int.class;
Class<Integer> integerClass1 = Integer.class;
Class<Integer> integerClass2 = Integer.TYPE;
  1. 对象.getClass()
    这是利用了Object提供的一个方法getClass() 来获取当着实例的Class对象。
  2. 使用Class类的静态方法forName()
	// 由于方法区 Class 类型信息由类加载器和类全限定名唯一确定,所以参数name必须是全限定名
    //参数说明 name:class名,initialize为true表示这个类将会初始化,loader 类加载器
	@CallerSensitive
    public static Class<?> forName(String name, boolean initialize,
                                   ClassLoader loader)
        throws ClassNotFoundException
    {
        Class<?> caller = null;
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            // Reflective call to get caller class is only needed if a security manager
            // is present.  Avoid the overhead of making this call otherwise.
            caller = Reflection.getCallerClass();
            if (sun.misc.VM.isSystemDomainLoader(loader)) {
                ClassLoader ccl = ClassLoader.getClassLoader(caller);
                if (!sun.misc.VM.isSystemDomainLoader(ccl)) {
                    sm.checkPermission(
                        SecurityConstants.GET_CLASSLOADER_PERMISSION);
                }
            }
        }
        //调用核心方法
        return forName0(name, initialize, loader, caller);
    }
     //核心方法
     private static native Class<?> forName0(String name, boolean initialize,
                                            ClassLoader loader,
                                            Class<?> caller)
        throws ClassNotFoundException;


	// 上个方法的重载,平时一般都使用这个。initialize为true。
	@CallerSensitive
    public static Class<?> forName(String className)
                throws ClassNotFoundException {
        Class<?> caller = Reflection.getCallerClass();
        return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
    }

五、常用方法

1. 获得类的构造方法
  • public Constructor[] getConstructors() :获取类对象的所有可见的构造函数

  • public Constructor[] getDeclaredConstructors():获取类对象的所有的构造函数

  • public Constructor getConstructor(Class… parameterTypes): 获取指定的可见的构造函数,参数为:指定构造函数的参数类型数组(就是参数列表的Class类型),如果该构造函数不可见或不存在,会抛出 NoSuchMethodException 异常

  • public Constructor getDeclaredConstructor(Class… parameterTypes) :获取指定的构造函数,参数为:指定构造函数的参数类型数组,无论构造函数可见性如何,均可获取

注意getConstructors()只能获得被public修饰的构造方法,如果要获得被(protected,default,private)修饰的构造方法,就要使用的getDeclaredConstructors()这个方法了。

getConstructors()的源码:

    public Constructor<?>[] getConstructors() throws SecurityException {
    	// 检查是否允许访问。如果访问被拒绝,则抛出SecurityException。
       checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
       // privateGetDeclaredConstructors(boolean publicOnly) 方法就是返回构造方法,参数为true就是只有public的构造方法
       return copyConstructors(privateGetDeclaredConstructors(true));
    }
    private static <U> Constructor<U>[] copyConstructors(Constructor<U>[] arg) {
    	// 使用克隆,得到当前类的所有构造函数 
       Constructor<U>[] out = arg.clone();
       // 使用ReflectionFactory构造一个对象,也是不使用构造方法构造对象的一种方式。
       ReflectionFactory fact = getReflectionFactory();
       // 遍历,将构造函数进行拷贝返回。
       for (int i = 0; i < out.length; i++) {
           out[i] = fact.copyConstructor(out[i]);
       }
       return out;
    }
2. 获得类的属性
  • public Field[] getFields():获取所有可见的字段信息,Field数组为类中声明的每一个字段保存一个Field 实例
  • public Field[] getDeclaredFields():获取所有的字段信息,但不包括继承的字段
  • public Field getField(String name) :通过字段名称获取字段信息,该字段必须可见,否则抛出异常
  • public Field getDeclaredField(String name) :通过字段名称获取字段信息,但不包括继承的字段

getConstructors()的源码:

    public Field[] getFields() throws SecurityException {
    	// 检查是否允许访问。如果访问被拒绝,则抛出SecurityException。
       checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
       return copyFields(privateGetPublicFields(null));
    }
    private static Field[] copyFields(Field[] arg) {
    	// 声明一个Filed的数组,用来存储
       Field[] out = new Field[arg.length];
       ReflectionFactory fact = getReflectionFactory();
       for (int i = 0; i < arg.length; i++) {
           out[i] = fact.copyField(arg[i]);
       }
       return out;
    }
3. 获得类的一般方法
  • public Method[] getMethods(): 获取所有可见的方法

  • public Method[] getDeclaredMethods() :获取所有的方法,无论是否可见,但不包括继承的方法

  • public Method getMethod(String name, Class… parameterTypes) :根据方法名和参数获取可见的方法

  • public Method getDeclaredMethod(String name, Class… parameterTypes):根据方法名和参数获取方法,无论是否可见

4. 获得注解
  • Class.getAnnotations() 获取所有的注解,包括自己声明的以及继承的
  • Class.getAnnotation(Class< A > annotationClass) 获取指定的注解,该注解可以是自己声明的,也可以是继承的
  • Class.getDeclaredAnnotations() 获取自己声明的注解
  1. 注解只有标注了@Inherited才能被子类继承
  2. 当某个类没有标注任何注解时,getAnnotations()和getDeclaredAnnotations()返回空数组
  3. 当某个注解查询不到时,getAnnotation(Class< A > annotationType)方法返回null
  4. 子类重写的方法,注解无法被继承,针对方法而言,getAnnotations()与getDeclaredAnnotations()返回的结果似乎永远都是一样的。
5. 判断类的类型的方法
返回值类型方法名备注
booleanisAnnotation()判断是不是注解
booleanisArray()判断是否为数组
booleanisEnum()判断是否为枚举类型
booleanisInterface()是否为接口类型
booleanisMemberClass()当且仅当基础类是成员类时,返回“true”
booleanisPrimitive()确定指定的“类”对象是否表示原始类型。
booleanisSynthetic()如果这个类是合成类,则返回’ true ';否则返回“false”。

六、其他

注:java中instanceof和getClass的区别分析
class A { }
class B extends A { }
Object o1 = new A();
Object o2 = new B();
o1 instanceof A => true
o1 instanceof B => false
o2 instanceof A => true // 注意1
o2 instanceof B => true
o1.getClass().equals(A.class) => true
o1.getClass().equals(B.class) => false
o2.getClass().equals(A.class) => false // 注意2
o2.getClass().equals(B.class) => true
instanceof 是子类的实例也会返回true,而getClass不会。

七、参考

https://www.cnblogs.com/chentang/p/13170081.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值