19 反射
19.1 类的加载概述和加载时机
19.1.1 类的加载概述
当程序要使用某个类时,如果该类还未加载到内存中,则系统会通过加载、连接、初始化三步来实现对这个类进行初始化。
- 加载:
指将class文件读入内存中,并为之创建一个Class对象,任何类被使用时系统都会建立一个Class对象。 - 连接:
- 验证:是否有正确的内部结构,并和其他类协调一致
- 准备:负责为类的静态成员分配内存,并设置默认初始化值
- 解析:将类的二进制数据中的符号引用替换为直接引用
- 初始化:即初始化步骤。
19.1.2 加载时机
- 创建类的实例
- 访问类的静态变量,或者为静态变量赋值
- 调用类的静态方法
- 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
- 初始化某个类的子类
- 直接使用java.exe命令来运行某个主类。
19.2 类加载器的概述和分类
19.2.1 类加载器的概述
- 负责将.class文件加载到内存中,并为之生成对应的Class对象。虽然我们并不关心类加载机制,但是了解这个机制可以更好理解程序运行。
19.2.2 类加载器的分类
- Bootstrap ClassLoader 根类加载器
- Extension ClassLoader 扩展类加载器
- System ClassLoader 系统类加载器
19.2.3 类加载器的作用
- Bootstrap ClassLoader 根类加载器
- 也称为引导类加载器,负责Java核心类的加载
- 比如System,String等,在JDK中JRE的lib目录下rt.jar文件中
- Extension ClassLoader 扩展类加载器
- 负责JRE的扩展目录中jar包的加载
- 在JDK中JRE的lib目录下ext目录
- System ClassLoader 系统类加载器
- 负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径
19.3 反射概述
- 概述
- JAVA反射机制是运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
- 对于任意一个对象,都能够调用他的任意一个方法和属性;
- 这种动态获取的信息以及动态调用的方法的功能称为java语言的反射机制;
- 想要解剖一个类,必须先要获取到该类的字节码文件对象;
- 而解剖使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应Class类型的对象。
例1:获取字节码文件对象的三种方式
Person.java
package com.mirror.gf;
public class Person {
private String name;
private int age;
public Person(){
super();
}
public Person(String name,int age){
super();
this.name = name;
this.age = age;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
Demo_Reflect.java
package com.mirror.gf;
public class Demo_Reflect {
public static void main(String[] args) throws ClassNotFoundException{
Class clazz1 = Class.forName("com.mirror.gf.Person");
Class clazz2 = Person.class;
Person p = new Person();
Class clazz3 = p.getClass();
System.out.println(clazz1== clazz2);
System.out.println(clazz2== clazz3);
}
}
运行结果:
ture
ture
例2:Class.forName()读取配置文件举例
Demo2_Reflect.java
package com.mirror.gf;
import java.io.BufferedReader;
import java.io.FileReader;
public class Demo2_Reflect {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
//使用反射与配置文件
BufferedReader br = new BufferedReader(new FileReader("config.properties"));
Class clazz = Class.forName(br.readLine());
Fruit f = (Fruit) clazz.newInstance();
Eat eat = new Eat();
eat.run(f);
br.close();
//未用反射
/*Eat eat = new Eat();
eat.run(new Orange());*/
}
}
interface Fruit{
public void eat();
}
class Apple implements Fruit{
public void eat(){
System.out.println("吃苹果");
}
}
class Orange implements Fruit{
public void eat(){
System.out.println("吃橙子");
}
}
class Eat{
public void run(Fruit f){
f.eat();
}
}
配置文件congfig.properties&#x