前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JDK源码解析之 java.lang.Class

JDK源码解析之 java.lang.Class

作者头像
栗筝i
发布2022-12-01 20:16:12
2270
发布2022-12-01 20:16:12
举报
文章被收录于专栏:迁移内容迁移内容

Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识。 这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建。

一、类定义

代码语言:javascript
复制
public final class Class<T> implements java.io.Serializable,
                              GenericDeclaration,
                              Type,
                              AnnotatedElement {}
  • Serializable:可被序列化的标志接口
  • GenericDeclaration:可以声明(定义)范型变量
  • Type:声明用的表示这是一个表示Type的东西
  • AnnotatedElement:表了在当前JVM中的一个“被注解元素”

二、常用方法

Class类没有公共的构造方法,无法通过new运算符实例化;只能通过对象的getClass方法,或是通过Class.forName(…)来获得实例。

1、getName()

一个Class对象描述了一个特定类的属性,Class类中最常用的方法getName以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。

代码语言:javascript
复制
    public String getName() {
        String name = this.name;
        if (name == null)
            this.name = name = getName0();
        return name;
    }

    // cache the name to reduce the number of calls into the VM
    private transient String name;
    private native String getName0();
2、newInstance()

可以为类创建一个实例

代码语言:javascript
复制
@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;
    }
}
private volatile transient Constructor<T> cachedConstructor;
private volatile transient Class<?>       newInstanceCallerCache;
3、getClassLoader()

返回该类的类加载器。

代码语言:javascript
复制
@CallerSensitive
public ClassLoader getClassLoader() {
    ClassLoader cl = getClassLoader0();
    if (cl == null)
        return null;
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
        ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass());
    }
    return cl;
4、getComponentType()

返回表示数组组件类型的 Class。

代码语言:javascript
复制
public native Class<?> getComponentType();
5、getSuperclass()

返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。

代码语言:javascript
复制
public native Class<? super T> getSuperclass();
6、isArray()

判定此 Class 对象是否表示一个数组类。

代码语言:javascript
复制
public native boolean isArray();
7、getSimpleName()

返回源代码中给出的基础类的简称。string

代码语言:javascript
复制
public String getSimpleName() {
    if (isArray())
        return getComponentType().getSimpleName()+"[]";

    String simpleName = getSimpleBinaryName();
    if (simpleName == null) { // top level class
        simpleName = getName();
        return simpleName.substring(simpleName.lastIndexOf(".")+1); // strip the package name
    }
    int length = simpleName.length();
    if (length < 1 || simpleName.charAt(0) != '$')
        throw new InternalError("Malformed class name");
    int index = 1;
    while (index < length && isAsciiDigit(simpleName.charAt(index)))
        index++;
    // Eventually, this is the empty string iff this is an anonymous class
    return simpleName.substring(index);
}
8、getDeclaredFields()

返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。

代码语言:javascript
复制
@CallerSensitive
public Field[] getDeclaredFields() throws SecurityException {
    checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
    return copyFields(privateGetDeclaredFields(false));
}

java.lang.reflect.Field主要是用于反射类的字段。反射经常用于工具类的开发,或中间件的开发。

三、总结

Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。 虚拟机为每种类型管理一个独一无二的Class对象。也就是说,每个类(型)都有一个Class对象。运行程序时,Java虚拟机(JVM)首先检查是否 所要加载的类对应的Class对象是否已经加载。如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。 基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也都对应一个 Class 对象。 每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。 一般某个类的Class对象被载入内存,它就用来创建这个类的所有对象。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-08-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、类定义
  • 二、常用方法
    • 1、getName()
      • 2、newInstance()
        • 3、getClassLoader()
          • 4、getComponentType()
            • 5、getSuperclass()
              • 6、isArray()
                • 7、getSimpleName()
                  • 8、getDeclaredFields()
                  • 三、总结
                  相关产品与服务
                  消息队列 TDMQ
                  消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档