A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 瞧瞧嗨一波... 于 2017-12-21 17:59 编辑

类装载器(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");
                //获取类的默认构造器对象并通过它实例化User
                Constructor 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");
                //实例化User
                PrivateUser 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));
        }
}

1 个回复

倒序浏览
已学习,谢谢
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马