java反射Reflection(一)之的类加载器ClassLoader和Class类

反射就是把Java的各种成分映射成相应的Java类。
  
  反射是java语言的一个特性,它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作。例如它允许一个java的类获取他所有的成员变量和方法并且显示出来。Java 的这一能力在实际应用中也许用得不是很多,但是在其它的程序设计语言中根本就不存在这一特性。例如,Pascal、C 或者 C++ 中就没有办法在程序中获得函数定义相关的信息。 

Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts on objects, within security restrictions. The API accommodates applications that need access to either the public members of a target object (based on its runtime class) or the members declared by a given class.

  上面这段是来自oracle官方文档。我自己的理解反射就是二进制的可执行文件或者java字节码(java code)能够在运行时获知自己的源代码(Source code)级别的信息。我们知道程序源代码被编译成机器指令后,相关的函数定义、字段等信息程序自己是无法看见的,也不知道,或者说已经没有了。特别是C、C++。对于java来说,Reflection机制就提供了程序自己发现自己源码级别信息的功能,这些源码级别的信息包括类、成员变量、成员函数名等。

 那java是如何在运行时也可以知道自己某个类的各种信息的呢?这里面先必须说下Class类,注意不是class关键字。我们知道java里面一切皆对象,一切皆类。那么java程序在运行时,首先得加载他需要的各种类的字节码,也就是我们的classname.class文件,每一个.class文件就和一个Class类对应起来,在jvm在加载这个.class文件的时候就会实例化一个Class类,并且这个Class类的构造方法是私有的。他只能由JVM创建。(这里其实是一个工厂模式),其他人不可以直接new出这个Class对象。这个Class类就描述了.class里面定义的类的各种信息,从而可以获取。

  类的加载又是又谁来完成呢?是类加载器ClassLoader的各种子类。包括BootStrap、ExtClassLoader、AppClassLoader、customClassLoader等。这些不同的ClassLoader负责加载不同级别的类。下图是是这几个ClassLoader的委托模型(Delegate Model也是java的一种重要设计模式)


下面是一个测试代码:

import java.util.Map.Entry;

public class TestJDKClassLoader {

	public static void main(String[] args) {

		TestJDKClassLoader t = new TestJDKClassLoader();
		t.testClassLoaderClientage();
		t.printSystemInfo();
	}
	
	public void testClassLoaderClientage() {
		ClassLoader loader = this.getClass().getClassLoader();
		System.out.println("本类的类加载器: " + loader.getClass().getName());
		System.out.println("SystemClassLoader: "+ ClassLoader.getSystemClassLoader().getClass()
				.getName());//和上面的等价

		if (loader != null) {
			System.out.println("String 类的类加载器: "+String.class.getClassLoader());//Bootstrap
			System.out.println("AppClassLoader的直接加载器: "
					+ loader.getClass().getClassLoader());//Bootstrap
			ClassLoader fatherLoader = loader.getParent();
			System.out.println("本类的爷爷加载器名称: "
					+ fatherLoader.getClass().getName());
		}
	}
	
	public void printSystemInfo(){
		for (Entry<Object, Object> entry : System.getProperties().entrySet()) { 
            System.out.println(entry.getKey()+"\t"+entry.getValue()); 
		}
	}
}
打印结果如下:

本类的类加载器: sun.misc.Launcher$AppClassLoader
SystemClassLoader: sun.misc.Launcher$AppClassLoader
String 类的类加载器: null
AppClassLoader的直接加载器: null
本类的爷爷加载器名称: sun.misc.Launcher$ExtClassLoader

(注:这里的null其实是bootstrap,因为这个类是本地语言实现的,在JVM里,所以看不到)
AppClassLoader负责加载当前运行环境下的类,及java.class.path,他在加载类的时候会向上委托,如果上面的已经加载了该类,自己就不在加载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值