Java基础进阶_day18_(类加载器,反射,动态代理)
博客专区 > Sunmos 的博客 > 博客详情
Java基础进阶_day18_(类加载器,反射,动态代理)
Sunmos 发表于1年前
Java基础进阶_day18_(类加载器,反射,动态代理)
  • 发表于 1年前
  • 阅读 2
  • 收藏 0
  • 点赞 0
  • 评论 0

移动开发云端新模式探索实践 >>>   

Java基础进阶_day18_(类加载器,反射,动态代理)

1. 类加载器

/* * 类加载器: * 类的加载:当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化. * 1.加载 * 就是指将class文件读入内存,并为之创建一个Class对象。 任何类被使用时系统都会建立一个Class对象。 * 2.连接 * A:验证 是否有正确的内部结构,并和其他类协调一致; * B:准备 负责为类的静态成员分配内存,并设置默认初始化值; * C:解析 将类的二进制数据中的符号引用替换为直接引用. * 3.初始化 * 就是我们以前讲过的初始化步骤. * 类的初始化时机: * 1.创建类的实例; * 2.访问类的静态变量,或者为静态变量赋值; * 3.调用类的静态方法; * 4.使用反射方式来强制创建某个类或接口对应的java.lang.Class对象; * 5.初始化某个类的子类; * 6.直接使用java.exe命令来运行某个主类. * * 类加载器:负责将.class文件加载到内在中,并为之生成对应的Class对象,获取到Class对象后结合反射进行使用. * 类加载器分为三种: * 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包和类路径. */
public class My_ClassLoader_Demo01 {
    public static void main(String[] args) {
    }
}

2.反射

2.1 反射概述

/* * 反射: * JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法; * 对于任意一个对象,都能够调用它的任意一个方法和属性; * 这种动态获取的信息以及动态调用对象的方法的功能. * 反射使用的前提是先获取类的字节码对象Class,使用Class中方法进行类的解析. * * 获取Class对象的三种方式:常用第三种 * A:通过类.class获取 * B:通过对象.getclass()方法获取 * C:通过Class的forName(类的全名)获取 */
public class My_Reflect_Demo01 {
    public static void main(String[] args) throws Exception {
        // 类的Class对象的获取
        // A:通过类.class获取
        Class c1 = My_Reflect_Demo01.class;
        System.out.println(c1);
        // B:通过对象.getclass()方法获取
        My_Reflect_Demo01 mrd = new My_Reflect_Demo01();
        Class c2 = mrd.getClass();
        System.out.println(c2);
        // C:通过Class的forName(类的全名)获取
        Class c3 = Class.forName("com.itheima.reflect01.My_Reflect_Demo01");
        System.out.println(c3);
    }
}

2.2 反射获取构造方法

package com.itheima.reflect02;
/* * 自定义类,反射测试用 */
public class Person {
    // 私有的属性
    private String name;
    // 默认的属性
    int age;
    // 无参构造方法
    public Person() {
    }
    // 有参构造方法
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // 私有的构造方法
    private Person(int age) {
        this.age = age;
    }
    // 公共的成员方法
    public void show(String s) {
        System.out.println("show:" + s);
    }
    // 私有的成员方法
    private String show2(String s) {
        return "私有的成员方法";
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
}

import java.lang.reflect.Constructor;
/* * 反射获取构造方法: * Class类的方法:获取构造方法的参数是对应数据类型的.class对象 * public Constructor[] getConstructors():获取所有的公共的构造方法; * public Constructor[] getDeclaredConstructors():获取所有的构造方法,包括私有的构造方法; * public Constructor getConstructor(Class... parameterTypes):获取指定参数个数和类型的公共的构造方法,没有参数时获取空参构造; * public Constructor getDeclaredConstructor(Class... parameterTypes):获取指定参数个数和类型的所有的构造方法,,没有参数时获取空参构造; * 创建类对象:Class类的方法 * public T newInstance(Object ... initargs):创建类的对象,参数为空时代表无参 * 当获取的是私有的构造方法时,创建对象前先调用setAccessible(boolean flag),将访问权限设为true. */
public class My_Reflect_Demo01 {
    public static void main(String[] args) throws Exception {
        // 获取类的Class对象
        Class c1 = Class.forName("com.itheima.reflect02.Person");
        // 获取所有公共的构造方法
        Constructor[] cs = c1.getConstructors();
        for (int i = 0; i < cs.length; i++) {
            System.out.println(cs[i]);
        }
        // 获取所有的构造方法
        Constructor[] cns = c1.getDeclaredConstructors();
        for (Constructor cn : cns) {
            System.out.println(cn);
        }
        // 获取单个构造方法,并创建对象
        Constructor cns1 = c1.getConstructor();
        Object obj = cns1.newInstance();
        // 获取私有的构造方法,并创建对象
        Constructor cns2 = c1.getDeclaredConstructor(int.class);
        cns2.setAccessible(true);
        Object obj2 = cns2.newInstance(23);
        System.out.println(obj2); // Person [name=null, age=23]
    }
}

2.3 反射获取成员属性

package com.itheima.reflect02;
/* * 自定义类,反射测试用 */
public class Person {
    // 私有的属性
    private String name;
    // 默认的属性
    int age;
    // 无参构造方法
    public Person() {
    }
    // 有参构造方法
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // 私有的构造方法
    private Person(int age) {
        this.age = age;
    }
    // 公共的成员方法
    public void show(String s) {
        System.out.println("show:" + s);
    }
    // 私有的成员方法
    private String show2(String s) {
        return "私有的成员方法";
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
}

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/* * 反射获取类的成员属性:Class类的功能 * public Field[] getFields():获取类的公共的成员属性; * public Field[] getDeclaredFields():获取类的所有的成员属性; * public Field getField(String name):获取类的指定字段名的公共的成员属性; * public Field getDeclaredField(String name):获取类的指定字段名的成员属性(可以是私有的属性). * 设置属性的值:Field类的功能 * public void set(Object obj,Object value):设置指定obj对象变量的此field表示的字段值设为value; * */
public class My_Reflect_Demo02 {
    public static void main(String[] args) throws Exception {
        // 获取类的Class对象
        Class c1 = Class.forName("com.itheima.reflect02.Person");
        // 获取构造方法,并创建对象
        Constructor cns = c1.getDeclaredConstructor(int.class);
        cns.setAccessible(true);
        Object obj = cns.newInstance(34);
        // 获取公共的成员属性
        Field[] fields = c1.getFields();
        // 获取所有的成员属性
        Field[] fields2 = c1.getDeclaredFields();
        for (Field field : fields2) {
            System.out.println(field);
        }
        // 获取制定字段名的属性,并设置新的值
        Field field = c1.getDeclaredField("name");
        field.setAccessible(true);
        field.set(obj, "java");
        System.out.println(obj);
    }
}

2.4 反射获取成员方法

package com.itheima.reflect02;
/* * 自定义类,反射测试用 */
public class Person {
    // 私有的属性
    private String name;
    // 默认的属性
    int age;
    // 无参构造方法
    public Person() {
    }
    // 有参构造方法
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    // 私有的构造方法
    private Person(int age) {
        this.age = age;
    }
    // 公共的成员方法
    public void show(String s) {
        System.out.println("show:" + s);
    }
    // 私有的成员方法
    private String show2(String s) {
        return "私有的成员方法";
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
}

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/* * 反射获取类的成员方法:Class类的方法 * public Method[] getMethods():获取所有的成员方法,包括由该类或接口声明的以及从超类和超接口继承的那些的类或接口的公共成员方法; * public Method getMethod(String name,Class... parameterTypes):获取该类指定名称及指定参数个数及类型的所有公共的方法,包括该类之上的所有类及接口的公共方法。 * public Method[] getDeclaredMethods():获取本类所有的成员方法; * public Method getDeclaredMethod(String name,Class... parameterTypes):获取本类指定名称和指定参数个数及参数类型方法. * 调用方法:Method类的方法 * public Object invoke(Object obj,Object... args):调用obj对象变量的该方法,参数是Object类型的数组,返回值是object类型. */
public class My_Reflect_Demo03 {
    public static void main(String[] args) throws Exception {
        // 获取类的Class对象
        Class c1 = Class.forName("com.itheima.reflect02.Person");
        // 获取构造方法,创建对象
        Constructor cns = c1.getDeclaredConstructor();
        Object obj = cns.newInstance();
        // 获取所有的成员方法
        Method[] methods = c1.getMethods();
        // Method[] methods = c1.getDeclaredMethods();
        // 获取指定参数的成员方法
        Method method = c1.getDeclaredMethod("show2", String.class);
        method.setAccessible(true);
        Object result = method.invoke(obj, "你好");
        System.out.println(result); // 私有的成员方法
    }
}

2.5 反射案例1

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
/* * ArrayList<Integer>的一个对象,在集合中存储字符串数据 */
public class My_Reflect_Test01 {
    public static void main(String[] args) throws Exception {
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(89);
        // 获取Class对象
        Class c1 = list.getClass();
        // 获取add方法,该方法的默认参数是E泛型,则是object的之类,将方法的参数设为object类型
        Method method = c1.getDeclaredMethod("add", Object.class);
        // 向集合中添加字符串数据
        method.invoke(list, "java");
        // 输出结果
        System.out.println(list);
    }
}

2.6 反射案例2

import java.lang.reflect.Field;
/* * 写一个方法public void setProperty(Object obj, String propertyName, Object value){}, * 此方法可将obj对象中名为propertyName的属性的值设置为value。 */
public class My_Reflect_Test02 {
    public static void main(String[] args) throws Exception {
        Person p = new Person();
        MyTool mt = new MyTool();
        mt.setProperty(p, "name", "张三");
        System.out.println(p);
    }
}
// 自定义类
class MyTool {
    // 定义方法
    public void setProperty(Object obj, String propertyName, Object value) throws Exception {
        // 获取对象的class对象
        Class c = obj.getClass();
        // 获取属性值的字段
        Field field = c.getDeclaredField(propertyName);
        // 将属性的访问权限设为true
        field.setAccessible(true);
        // 将obj对象的某个字段值设为value
        field.set(obj, value);
    }
}
  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 0
博文 34
码字总数 0
×
Sunmos
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: