java中的class类

Class类简述

class 类和 java.lang.String, java.lang.Integer 或是我们自定义的类一样,都是java中的类,都继承自 java.lang.Object, 只不过名字比较特殊。

对于我们自己定义的类,我们用类来抽象现实中的某些事物,比如我们定义一个名称为 Car 的类来抽象现实生活中的车,然后可以实例化这个类,用这些实例来表示我的车、你的车、黄的车、红的车等等。

我们通过 Car 类创建出对象实例,这些对象实例是 Car 这个类所抽象的事物的具体实现。 同时我们可以创建出名为 Class 的类的对象实例,这些通过 Class 类创建出的对象代表的是Java中运行着的各个类。

Car 这个类中可能有 代表车尺寸的 lengthHeight 等属性, 同样的 Class 这个类中也有表示各个类名称的 name 属性等。

一句话: 类是对事物的抽象, Class 又是对这些类的一个抽象。

我们编写一个没有任何自定义方法和属性的类 ClassTest 来说明 Class 类的相关使用。

package cn.wang.myclasses;

/**
 * cn.wang.myclasses.ClassTest
 *
 * @author Yang
 * @date 2018/5/9
 */

public class ClassTest {
    public static void main(String args[]) {
        ClassTest myClass = new ClassTest();
        ...
    }
}

获取Class类

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虚拟机能调用该方法创建该类的对象,所以我们不能像其他类一样用 new 关键字获取对象。但有下面几种方法可以获取到具体 Class 对象

1. 通过类的静态成员获取。每个类都有一个表示其 Class 对象的静态成员

    Class clazz1 = ClassTest.class;

2. 通过对象的 getClass() 方法获取。不难猜出此方法是继承自 java.lang.Object 类的方法。

    Class clazz2 = myClass.getClass();

3. 通过 Class 类的静态方法 forName() 方法获取 Class 的对象,该方法可以帮助我们实现在程序运行时类的动态加载

    try {
        clazz3 = Class.forName("cn.wang.myclasses.ClassTest");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }

Class类相关方法

newInstance 方法

我们可以通过 MyClass 对象获取其对应的 Class 类的对象, 也可以通过 Class 类对象获取普通类的对象

    ClassTest myClass2 = (ClassTest) clazz1.newInstance();

newInstance() 获取类对象时要求类必须有无参构造方法,否则会抛出 InstantiationException 异常:

Exception in thread "main" java.lang.InstantiationException: cn.wang.myclasses.NoNoneParaConstructor
    at java.lang.Class.newInstance(Class.java:427)
    at cn.wang.myclasses.ClassTest.main(ClassTest.java:40)
Caused by: java.lang.NoSuchMethodException: cn.wang.myclasses.NoNoneParaConstructor.<init>()
    at java.lang.Class.getConstructor0(Class.java:3082)
    at java.lang.Class.newInstance(Class.java:412)
    ... 1 more

forName(String name) 方法

此方法的作用前面已经提到,就是根据类的全限定名 className 查找 对应的 Class 实例,然后返回此实例的引用。

我们看到,此方法最终是调用一个名为 forName0 的方法,而 forName0 是一个本地方法。

@CallerSensitive
public static Class<?> forName(String className)
            throws ClassNotFoundException {
    Class<?> caller = Reflection.getCallerClass();
    return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}

/** Called after security check for system loader access checks have been made. */
private static native Class<?> forName0(String name, boolean initialize,
                                        ClassLoader loader,
                                        Class<?> caller)
    throws ClassNotFoundException;

getName() 方法

此方法返回该 Class 对象所对应的类的全限定名:

System.out.println("clazz1: " + clazz1.getName());
System.out.println("clazz1.getClass(): " + clazz1.getClass().getName());

//输出:
// clazz1: cn.wang.myclasses.ClassTest
// clazz1.getClass(): java.lang.Class

clazz1ClassTest 类对应的 Class 对象, 因此其调用 getName() 输出的是 ClassTest 的全限定名
clazz1.getClass()Class 类的 Class 对象, 因此对应输出是 java.lang.Class

    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();

我们看到, getName() 方法在第一次调用时会调用另一个本地方法 getName0() , 然后把得到的 name 缓存起来

getClassLoader() 方法

此方法返回加载调用此方法类的类加载器

Class clazz1 = ClassTest.class;
ClassLoader cl = clazz1.getClassLoader();
System.out.println("clazz1 classLoader: " + cl.toString());

Class stringClazz = String.class;
System.out.println("stringClazz classLoader: " + stringClazz.getClassLoader());

//输出:
// clazz1 classLoader: sun.misc.Launcher$AppClassLoader@18b4aac2
// stringClazz classLoader: null

我们看到,ClassTest 对应的类加载器是:应用程序类加载器 sun.misc.Launcher$AppClassLoaderString 的类加载器返回 null, 说明其加载器是启动类加载器

getSuperClass() 方法

此方法返回调用者对应的类的父类的 Class 对象

Class parentClazz = clazz1.getSuperclass();
System.out.println("parentClazz: " + parentClazz.getName());

//输出:
//parentClazz: java.lang.Object

ClassTest 的父类是 Object

此方法也是一个本地方法。

    public native Class<? super T> getSuperclass();

猜你喜欢

转载自blog.csdn.net/wy11933/article/details/80256414