Class.forName("com.mysql.jdbc.Driver"); Class.forName("oracle.jdbc.OracleDriver"); Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");这里其实是用到了类加载器ClassLoader:
// ClassLoader loader = ReflectTest.class.getClassLoader(); ClassLoader loader = Thread.currentThread().getContextClassLoader();然后可以进行一些操作了:
//获取声明的构造方法(任何权限修饰符的),此处为默认的无参构造,如要生成有参的,只需传入相应参数的类型Class对象 Constructor cons = clazz.getDeclaredConstructor(); //创建对象 Car car = (Car) cons.newInstance(); //根据传入方法的参数的类型,获取setBrand方法 Method setBrand = clazz.getMethod("setBrand", String.class); //回调方法 setBrand.invoke(car, "红旗CA72"); //同理 Method setMaxSpeed = clazz.getMethod("setMaxSpeed", int.class); setMaxSpeed.invoke(car, 200);问题来了,如果我们获取一个类的方法或属性是非public的,我们访问一个非public的方法或属性时如果不加设置会抛出异常: java.lang.IllegalAccessException
// 获取private属性 Field colorFld = clazz.getDeclaredField("color"); // 设置可访问 colorFld.setAccessible(true); colorFld.set(pcar, "红色"); // 获得private声明的方法 Method driveMtd = clazz.getDeclaredMethod("drive"); // 设置可访问 driveMtd.setAccessible(true); driveMtd.invoke(pcar, (Object[]) null);Java反射机制在诸多的框架中应用很广泛,我们在开发中常用的也不多,如需要自己编写一些框架,底层是逃离不了对Java反射的运用的,在JDK中reflect包中提供了这些类和接口,详细的可以在API中找到。
public class ClassLoaderTest { public static void main(String[] args) { //获取当前线程上下文的类加载器 ClassLoader loader = Thread.currentThread().getContextClassLoader(); // ClassLoader loader = ClassLoaderTest.class.getClassLoader(); System.out.println("Current loader:"+loader);//当前类加载器 System.out.println("Parent loader:"+loader.getParent());//父加载器 System.out.println("Grandparent loader:"+loader.getParent().getParent()); } }
Current loader:sun.misc.Launcher$AppClassLoader@6b97fd Parent loader:sun.misc.Launcher$ExtClassLoader@1c78e57 Grandparent loader:null@ClassLoader:根装载器,负责装载JRE的核心类库,如JRE目标下的charsets.jar和rt.jar等,在Java中访问不到,无法获得它的句柄,返回null。
Class loadClass(String name) name参数指定类装载器需要装载类的名字,必须使用全限定类名,如com.baobaotao. beans.Car。
该方法有一个重载方法loadClass(Stringname ,boolean resolve),resolve参数告诉类装载器是否需要解析该类。在初始化类之前,应考虑进行类解析的工作,
但并不是所有的类都需要解析,如果JVM只需要知道该类是否存在或找出该类的超类,那么就不需要进行解析。
Class findSystemClass(String name) 从本地文件系统载入Class文件,如果本地文件系统不存在该Class文件,将抛出ClassNotFoundException异常。该方法是JVM默认使用的装载机制。
Class findLoadedClass(String name) 调用该方法来查看ClassLoader是否已装入某个类。如果已装入,那么返回java.lang.Class对象,否则返回null。如果强行装载已存在的类,将会抛出链接错误。
ClassLoadergetParent() 获取类装载器的父装载器,除根装载器外,所有的类装载器都有且仅有一个父装载器,ExtClassLoader的父装载器是根装载器,因为根装载器非Java编写,所以无法获得,将返回null。