java基础知识穿插:类装载器;反射

来源:互联网 发布:java泛型和集合 中文 编辑:程序博客网 时间:2024/05/17 08:27

类装载器(ClassLoader):

定义:ClassLoader就是寻找类的字节码文件,并构造出类在JVM内部表示的对象组件。JVM运行时产生三个ClassLoader:根装载器、ExtClassLoader(扩展类装载器)、AppClassLoader(系统类装载器)。根装载器并不是ClassLoader的子类(由C++编写),ExtClassLoader和AppClassLoader都是ClassLoader的子类

ExtClassLoader:负责装载JRE扩展目录ext中的JAR类包

AppClassLoader:负责装载ClassPath路径下的类包

根装载器:负责装载JRE的核心类库,比如:rt.jar、charsets.jar;


ClassLoader将一个类装入JVM需要以下步骤:

1.装载:查找和导入Class文件;

2.链接:执行校验、准备和解析步骤,其中解析步骤是可选的:

a.校验:检查载入Class文件数据的正确性;

b.准备:给类的静态文件分配存储空间;

c.解析:将符号引用转成直接引用;

3.初始化:对类的静态变量和静态代码块执行初始化工作。


ClassLoader重要方法:

Class loadClass(String name):装载

Class loadClass(String name, boolean resolve):重载,resolve是否需要解析,并不是所有类在初始化的时候都要解析的

Class defineClass(String name, byte[], int off, int len):将类问件的字节数组转换成JVM内部的java.lang.Class对象

Class findSystemClass(String name):从本地文件系统加载一个Class问件,如果文件不存在就抛出ClassNotFoundException异常,JVM默认的装载机制

Class findLoadedClass(String name):查看ClassLoader是否装载了某个类

ClassLoader getParent():获取类装载器的父装载器。


java.lang.NoSuchMethodError:是由于JVM的全盘委托机制导致的,出现情景一般在:同时引用了commons-lang 2.x.jar 和 commons-lang 3.x.jar,JVM加载类时从commons-lang 2.x.jar中加载类,而代码中使用的却是commons-lang 3.x.jar中的方法,该方法在commons-lang 2.x.jar中并没有,此时,就会抛出该异常。


举例说明使用方法:

/** 测试实体 */public class User{private String name;//默认构造器public User(){}//带参构造器public User(String name){ this.name = name;}public String getName(){ return this.name; }public void setName(String Name){ this.name = name;}public void talk(){ System.out.println("hello, my name is " + this.name);}}
/** 测试方法 */public class test{private User initUser()throws Thtowable{//通过类装载器获取User对象ClassLoader loader = Thread.currentThread().getContextClassLoader();Calss clazz = loader.loadClass("com.taobao.entity.User");//获取类的默认构造器对象并通过它实例化UserConstructor cons = clazz.getDeclaredConstructor((class[])null);User user = (User)cons.newInstance();//通过反射方法设置属性Method setName = clazz.getMethod("setName", String.class);setName.invoke(user, "老王");return user;}public static void main(String[] args) throws Thtowable{User user = this.initUser();user.talk();}}


反射机制(reflect):

定义:Class反射对象描述类语意结构,可以从Class对象中获取构造函数、成员变量、方法等类元素的反射对象,并以编程的方式通过这些反射对象对目标类对象进行操作。这些反射对象类在java.reflect包中定义。

最主要的三个反射类:

Constructor:类的构造方法的反射类,通过Class.getConstructor()方法可以获得类的所有构造函数反射对象数组。在JDK5.0中,可以通过getConstrustor(Class parameterTypes)获取拥有特定参数的构造函数反射对象。Construstor主要方法是newInstance(Object[] initargs),创建一个对象实例。

Method:类方法的反射类,通过Class.getDeclaredMethod()方法可以获得类的所有方法反射对象数组Method[] 。在JDK5.0中,可以通过getDeclaredMethod(String name, Class parameterTypes)获取拥有特定参数的构造函数反射对象。Method主要方法是:

invoke(Object obj, Object...args):操作目标对象

Class getReturnType():获取方法返回值类型

Class[] getParameterTypes():获取方法的入参类型数组

Class[] getExceptionTypes():获取方法的异常类型数组

Annotation[][] getParameterAnnotations() :获取方法的注解信息,JDK5.0中的新方法

Field:类的成员变量的反射类,通过Class.getDeclaredFields()方法可以获得类的成员变量反射对象数组,通过Class.getDeclaredField(String name)可以获取某个特定成员对象的放射对象,Field主要方法:

set(Object obj, Object value):操作目标对象,通过value为目标对象的成员变量设置值

setBoolean(Object obj, boolean value);setInt(Object obj, int value);带类型名的值设置方法


举例说明使用方法:

/** 测试实体 */public class PrivateUser{//私有成员变量,外部不可引用private String name;//受保护成员方法,只有子类和本包中可以访问protected void talk(){ System.out.println("hello, my name is " + this.name);}}

/** 测试方法 */public class test{private User initUser()throws Thtowable{//通过类装载器获取User对象ClassLoader loader = Thread.currentThread().getContextClassLoader();Calss clazz = loader.loadClass("com.taobao.entity.PrivateUser");//实例化UserPrivateUser user = (PrivateUser)clazz.newInstance();//获取名为name的成员变量的反射对象Field nameFld = clazz.getDeclaredField("name");//获取名为talk的成员方法的反射对象Method talkMtd = clazz.getDeclaredMethod("talk", (Class[]null));/*Method talkMtd = clazz.getDeclaredMethod("talk"); JDK5.0下使用*///取消Java语言访问检查以访问private变量nameFld.setAccessible(true);nameFld.set(user, "老王");//取消Java语言访问检查以访问protected方法talkMtd.setAccessible(true);talkMtd.invoke(user, (Object[]null));}}

















原创粉丝点击