1.学习反射之前要了解下类是如何加载的
A:类的加载概述
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初 始化。
加载
就是指将class文件读入内存,并为之创建一个Class对象。任何类被使用时系统都会建立一个Class对象。
* 连接
a.验证 是否有正确的内部结构,并和其他类协调一致
b.准备 负责为类的静态成员分配内存,并设置默认初始化值
c.解析 将类的二进制数据中的符号引用替换为直接引用
初始化 就是我们以前讲过的初始化步骤
B.加载时机
* 创建类的实例
* 访问类的静态变量,或者为静态变量赋值
* 调用类的静态方法
* 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
* 初始化某个类的子类
* 直接使用java.exe命令来运行某个主类
C.类加载器的概述
* 负责将.class文件加载到内存中,并为之生成对应的Class对象。
D:类加载器的分类
* Bootstrap ClassLoader 根类加载器
* Extension ClassLoader 扩展类加载器
* Sysetm ClassLoader 系统类加载器
E:类加载器的作用
* Bootstrap ClassLoader 根类加载器
* 也被称为引导类加载器,负责Java核心类的加载
* 比如System,String等。在JDK中JRE的lib目录下rt.jar文件中
* Extension ClassLoader 扩展类加载器
* 负责JRE的扩展目录中jar包的加载。
* 在JDK中JRE的lib目录下ext目录
* Sysetm ClassLoader 系统类加载器
* 负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径
2.什么是反射?
* JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
* 对于任意一个对象,都能够调用它的任意一个方法和属性;
* 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
* 要想解剖一个类,必须先要获取到该类的字节码文件对象。
* 而解剖使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象。
3.反射的三种方式
a:Object类的getClass()方法,判断两个对象是否是同一个字节码文件
b:静态属性class,锁对象
c:Class类中静态方法forName(),读取配置文件
反射的三个阶段
获取Class对象的三种方式
通过Class来创建类的实例对象
- package com.heima.reflect;
- public class Demo02_Reflect {
- /**
- * 榨汁机榨汁案例来看通过Class对象如何来创建对象
- *
- */
- public static void main(String[] args) throws Exception {
- String[] s = {"com.heima.reflect.Orange", "com.heima.reflect.Apple"};
- Class clazz = Class.forName(s[1]); //动态加载类 获取该类的Class对象
- //创建此Class对象所表示的类的新实例,该实例是Object类型的,需要强制类型转换
- Fruit f = (Fruit) clazz.newInstance(); //父类的引用引用子类的对象
- Juicer j = new Juicer(); //创建榨汁机实例
- j.squeeze(f); //将水果对象放入榨汁机
- }
- }
- abstract class Fruit { //水果类
- public abstract String getName();
- }
- class Apple extends Fruit {
- private String name = "苹果";
- public String getName() {
- return name;
- }
- }
- class Orange extends Fruit {
- private String name = "橙子";
- public String getName() {
- return name;
- }
- }
- class Juicer { //榨汁机
- public void squeeze(Fruit f) {
- System.out.println("榨出一杯" + f.getName() + "汁");
- }
- }
复制代码
|
|