Java反射获取Class类对象

反射:能够分析类能力的程序称为反射,印象中sun公司在最初的两个版本就已经在jdk中发布了有关反向的声明,反射的功能及其强大,那它能做些什么呢?

  • 在运行时分析类的能力
  • 在运行时查看对象
  • 实现通用的数组操作代码
  • 利用Method对象,这个对象很想C++中的指针

看起来貌似很难理解,实际上呢,就是不好理解,索性就慢慢渗透吧。。。

反射是一种功能及其强大且复杂的机制,使用它的主要人员是工具的构造者,这里注意是构造者,一般我们都是使用一个工具,很少去向这些工具的生成原理,嘿,这里不就遇到了吗,就是利用复杂的反射,当然还有别的复杂机制,好了,不多说了,先看一下下面的基础知识。。


无论是百度百科,开始查看各种专业资料,学习Java反射最先接触的很定是Class对象,什么是Class对象呢?引用《Java核心技术》中的讲解:

在程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识,这个信息跟踪者每个对象所属的类。虚拟机利用运行时类型信息选择相应的方法执行。然而,可以通过专门的Java类访问这些信息,保存这些信息的类被称为Class。

下面是Class类定义的源码,核心代码是看不到的:

public final class Class<T> implements java.io.Serializable,
                              GenericDeclaration,
                              Type,
                              AnnotatedElement {
    private static final int ANNOTATION= 0x00002000;
    private static final int ENUM      = 0x00004000;
    private static final int SYNTHETIC = 0x00001000;

    private static native void registerNatives();
    static {
        registerNatives();
    }

    /*
     * Private constructor. Only the Java Virtual Machine creates Class objects.
     * This constructor is not used and prevents the default constructor being
     * generated.
     */
    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;
    }

......
}

这个类中定义了很多的方法,就不多说了,感兴趣可以自己翻一下源码。。当然有一些方法我们之后还会用得到。就比如说我们获取Class类对象就用到的forName()方法。。。


我们接下来看一下获取Class类对象的实现:

比如一个Person对象表示一个特定的人员属性一样,一个Class对象将表示一个特定类的属性,最常用的Class方法是getName()。该方法可以获取指定类的类名,如果这个类在一个包里,包的名字也会作为类名的一部分。除了这种方法,我们还可以用上面说到的forName()方法,这是个静态方法,我们可以看一下Class类中定义该方法的源码:

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

    /** 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;

如果类名保存在字符串中,并且可以在运行中改变,比较适合使用这个静态方法。当然,这个方法之后再className(代码看下面)是类名或者接口名的时候才可以执行。否则,forName方法将抛出一个checked exception 异常。注意:无论何时在使用这个方法,都应该提供一个异常处理器。

package reflection;

import java.util.Random;

/*
 * 反射  获取Class类对象的三种方式
 * 1、根据对象实例 调用 o.getClass().getName()方法
 * 2、调用静态的forName()方法
 * 3、根据Java类型也可以获取Class类对象
 */
public class Test1 {
	
	public static void main(String[] args) {
		
		Person p = new Person();
		p.setAge(20);
		p.setName("China");
		System.out.println(p.getClass().getName() + " " + p.getName());
		
		Random generator = new Random();
		Class cl = generator.getClass();
		String name = cl.getName();
		System.out.println("name : " + name);
		
		String className = "java.util.Random";
		try {
			Class cl2 = Class.forName(className);
			System.out.println(cl2.getName());
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		Class cl3 = int.class;
		System.out.println(cl3);
		
	}
}

如果T是任意的Java类型,T.class将代表匹配的类对象。上面的代码中也有体现。

一个Class对象实际上指的是一个类型,而这个类型未必是一种类,就比如int.class不是类,但是int.class是一个Class类型的对象。

猜你喜欢

转载自blog.csdn.net/IBLiplus/article/details/82981544