一、类加载器
Java类加载器(Java Classloader)是Java运行时环境(Java Runtime Environment)的一部分,负责动态加载Java类到Java虚拟机的内存空间中。
(一)类加载的时机
- 创建类的实例(对象)
- 调用类的类方法
- 访问类或者接口的类变量,或者为该类变量赋值
- 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
- 初始化某个类的子类
- 直接使用java.exe命令来运行某个主类
(二)类加载的过程
- 加载 : 通过包名 + 类名,获取这个类,准备用流进行传输;在这个类加载到内存中加载完毕创建一个class对象
- 链接:
- 验证 :确保Class文件字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身安全(文件中的信息是否符合虚拟机规范有没有安全隐患)
- 准备:负责为类的类变量(被static修饰的变量)分配内存,并设置默认初始化值(初始化静态变量)
- 解析:将类的二进制数据流中的符号引用替换为直接引用(本类中如果用到了其他类,此时就需要找到对应的类)
- 初始化:根据程序员通过程序制定的主观计划去初始化类变量和其他资源(静态变量赋值以及初始化其他资源)
(三)类加载器分类
-
Bootstrap class loader:虚拟机的内置类加载器,通常表示为null ,并且没有父null
-
Platform class loader:平台类加载器,负责加载JDK中一些特殊的模块
-
System class loader:系统类加载器,负责加载用户类路径上所指定的类库
(四)继承关系
- System的父加载器为Platform
- Platform的父加载器为Bootstrap
代码:
public class ClassLoaderDemo1 {
public static void main(String[] args) {
//获取系统类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
//获取系统类加载器的父加载器 --- 平台类加载器
ClassLoader classLoader1 = systemClassLoader.getParent();
//获取平台类加载器的父加载器 --- 启动类加载器
ClassLoader classLoader2 = classLoader1.getParent();
System.out.println("系统类加载器" + systemClassLoader);
System.out.println("平台类加载器" + classLoader1);
System.out.println("启动类加载器" + classLoader2);
}
}
(五)双亲委派模型
如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器,如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式。
二、反射
(一)概述
Java 反射机制是Java语言一个很重要的特性,它使得Java具有了“动 态性”。在Java程序运行时,对于任意的一个类,我们能不能知道这 个类有哪些属性和方法呢?对于任意的一个对象,我们又能不能调 用它任意的方法?答案是肯定的!这种动态获取类的信息以及动态 调用对象方法的功能就来自于Java 语言的反射(Reflection)机 制。
(二)反射的作用
简单来说两个作用,RTTI(运行时类型识别)和DC(动态创建)。 我们知道反射机制允许程序在运行时取得任何一个已知名称的class 的内部信息,包括其modifiers(修饰符),fields(属性),methods(方 法)等,并可于运行时改变fields内容或调用methods。那么我们便 可以更灵活的编写代码,代码可以在运行时装配,无需在组件之间 进行源代码链接,降低代码的耦合度;还有动态代理的实现等等; 但是需要注意的是反射使用不当会造成很高的资源消耗!实际上,我们在加载任何一个类时都会在方法区中建立“这个类对应 的Class对象”,由于“Class对象”包含了这个类的整个结构信息,所 以我们可以通过这个“Class对象”来操作这个类。 我们要使用一个类,首先要加载类;加载完类之后,在堆内存中, 就产生了一个 Class 类型的对象(一个类只有一个 Class 对象), 这个对象就包含了完整的类的结构信息。我们可以通过这个对象知 道类的结构。这个对象就像一面镜子,透过这个镜子可以看到类的 结构,所以,我们形象的称之为:反射。 因此,“Class对象”是反射 机制的核心。
(三)获取Class对象的三种方式
通过getClass()方法; 通过.class 静态属性; 通过Class类中的静态方法forName();
代码示例
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void study(){
System.out.println("学生在学习");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class ReflectDemo1 {
public static void main(String[] args) throws ClassNotFoundException {
//1.Class类中的静态方法forName("全类名")
//全类名:包名 + 类名
Class clazz = Class.forName("com.tmh.myreflect2.Student");
System.out.println(clazz);
//2.通过class属性来获取
Class clazz2 = Student.class;
System.out.println(clazz2);
//3.利用对象的getClass方法来获取class对象
//getClass方法是定义在Object类中.
Student s = new Student();
Class clazz3 = s.getClass();
System.out.println(clazz3);
System.out.println(clazz == clazz2);
System.out.println(clazz2 == clazz3);
}
}
(四)反射获取构造方法并使用
方法如下:
Constructor<?>[] getConstructors() | 返回所有公共构造方法对象的数组 |
Constructor<?>[] getDeclaredConstructors() | 返回所有构造方法对象的数组 |
Constructor<T> getConstructor(Class<?>... parameterTypes) | 返回单个公共构造方法对象 |
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) | 返回单个构造方法对象 |
(四)Constructor类用于创建对象的方法
T newInstance(Object...initargs) | 根据指定的构造方法创建对象 |
setAccessible(boolean flag) | 设置为true,表示取消访问检查 |
(五)反射获取成员变量并使用
常用方法:
Field[] getFields() | 返回所有公共成员变量对象的数组 |
Field[] getDeclaredFields() | 返回所有成员变量对象的数组 |
Field getField(String name) | 返回单个公共成员变量对象 |
Field getDeclaredField(String name) | 返回单个成员变量对象 |
Field类用于给成员变量赋值的方法:
void set(Object obj, Object value) | 赋值 |
Object get(Object obj) | 获取值 |
(六)反射获取成员方法并使用
Method[] getMethods() | 返回所有公共成员方法对象的数组,包括继承的 |
Method[] getDeclaredMethods() | 返回所有成员方法对象的数组,不包括继承的 |
Method getMethod(String name, Class<?>... parameterTypes) | 返回单个公共成员方法对象 |
Method getDeclaredMethod(String name, Class<?>... parameterTypes) | 返回单个成员方法对象 |
Method类用于执行方法的方法
Object invoke(Object obj, Object... args) | 运行方法 |