反射

类的加载

  1. 概述:当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现类的初始化
  2. 加载时机:
    (1)创建类对象时
    (2)访问类的静态变量或调用类的静态方法
    (3)通过反射来创建类对象
    (4)初始化某个类的子类
    (5)通过java.exe命令运行某个类

类加载器

  1. 概述:将.class文件加载到内存中,并生成对应的.class对象
  2. 分类及其作用:
    在这里插入图片描述

反射

  1. 概述:就是在运行状态中的一种动态调用类的方法或者属性的一种机制,即获取字节码文件对象,然后刨析类中的成员变量,构造方法,成员方法
  2. 获取class文件对象的三种方式
    (1)Object类的getClass()方法
    (2)静态属性class
    (3)class类中静态方法forName()
package org.westos2.demo2;

public class MyTest {
    public static void main(String[] args) throws ClassNotFoundException {
        //通过getClass方法获取字节码对象
        Student student = new Student();
        Class aClass1 = student.getClass();
        Class aClass2 = student.getClass();
        System.out.println(aClass1==aClass2);
        //通过类的静态属性class获取字节码对象
        Class aClass = Student.class;
        System.out.println(aClass==aClass1);
        //通过Class中的forName方法获取字节码对象
        //参数需要传入类的全限定名:包名+类名
        Class aClass3 = Class.forName("org.westos2.demo2.Student");
        System.out.println(aClass3==aClass2);
    }
}

在这里插入图片描述
结果表明,代码中的几个对象都是同一个对象,因为一个类只有一个.class文件

一个类的由三部分构成:构造方法(ConStructor)、成员变量(Field)、成员方法(Method)
下面通过反射来刨析类的构成:

  1. 获取构造方法(空参构造,有参构造,私有构造)
package org.westos2.demo2;

public class Student {
    //空参构造
    public Student() {
        System.out.println("执行空参构造");
    }
    //有参构造
    public Student(String name) {
        System.out.println("执行有参构造");
    }
    //私有构造
    private Student(String name,int age) {
        System.out.println("执行私有构造");
    }
}

package org.westos2.demo2;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class MyTest {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //获取字节码对象
        Class aClass = Student.class;

        //通过getConstructors方法获取所有构造方法对象,私有的除外
        Constructor[] constructors = aClass.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        System.out.println("-------------------------------");

        //通过getDeclaredConstructors方法获取所有构造方法对象,包括私有
        Constructor[] declaredConstructors = aClass.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        System.out.println("-------------------------------");

        //通过getConstructor获取空参构造对象
        //并通过newInstance创建一个该类实例
        Constructor constructor = aClass.getConstructor();
        Student student = (Student) constructor.newInstance();
        System.out.println(student);

        //通过getConstructor,传入参数的class类型,获取空参构造对象,不能获取私有的
        //并通过newInstance创建一个该类实例
        Constructor constructor1 = aClass.getConstructor(String.class);
        Student student1 = (Student) constructor1.newInstance("张三");
        System.out.println(student1);

        //通过getDeclaredConstructor获取私有构造对象
        //通过setAccessible取消语法检测
        //并通过newInstance创建一个该类实例
        Constructor declaredConstructor = aClass.getDeclaredConstructor(String.class, int.class);
        declaredConstructor.setAccessible(true);
        Object o =  declaredConstructor.newInstance("张三", 23);
        System.out.println(o);
    }
}

在这里插入图片描述

  1. 获取成员变量(公共成员变量,私有成员变量)
package org.westos2.demo3;

public class Student {
    //成员变量
    public String name;
    //私有成员变量
    private int age;
}
package org.westos2.demo3;

import java.lang.reflect.Field;

public class MyTest {
    public static void main(String[] args) throws Exception {
        //获取字节码对象
        Class aClass = Class.forName("org.westos2.demo3.Student");
        //通过getFields方法获取类中所有字段对象,私有的除外
        Field[] fields = aClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("-------------------------------");

        //通过getDeclaredFields方法获取类中所有字段对象,包括私有
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        System.out.println("-------------------------------");

        //通过getField方法获取单个字段对象,不适合私有
        Field name = aClass.getField("name");
        //获取构造方法对象
        Object o = aClass.getConstructor().newInstance();
        //给字段赋值
        name.set(o,"张三");
        //获取字段值
        Object o1 = name.get(o);
        System.out.println(o1);


        //通过getDeclaredField方法获取私有单个字段对象
        Field age = aClass.getDeclaredField("age");
        //取消私有语法检测
        age.setAccessible(true);
        //给私有字段赋值
        age.set(o,23);
        //获取私有字段的值
        Object o2 = age.get(o);
        System.out.println(o2);
    }
}

在这里插入图片描述

  1. 获取成员方法(无参无返回值、有参带返回值、私有方法)
package org.westos2.demo4;

public class Student {
    //无参无返回值成员方法
    public void method1(){
        System.out.println("这是一个无参无返回值成员方法");
    }
    //有参带返回值成员方法
    public int method2(String name){
        System.out.println("这是一个有参带返回值成员方法");
        return 18;
    }
    //私有方法
    private int method(String name,int num){
        System.out.println("这是一个私有方法");
        return 18+num;
    }
}
package org.westos2.demo4;

import java.lang.reflect.Method;

public class MyTest {
    public static void main(String[] args) throws Exception {
        //获取字节码对象
        Class aClass = Student.class;
        //通过getMethods方法获取所有方法对象,包括父类的,不包括私有
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("----------------------------------");

        //通过getDeclaredMethods获取该类所有方法对象,包括私有
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        System.out.println("----------------------------------");

        //通过getMethod获取单个方法对象,参数1代表方法名称,参数2代表方法参数的字节码类型
        Method method1 = aClass.getMethod("method1");
        System.out.println(method1);
        //让空参方法执行
        //获取构造方法实例
        Object o = aClass.getConstructor().newInstance();
        //通过invoke让方法执行
        Object invoke = method1.invoke(o);
        System.out.println(invoke);
        System.out.println("----------------------------------");

        //获取有参方法对象
        Method method2 = aClass.getMethod("method2", String.class);
        System.out.println(method2);
        //让有参方法执行
        Object invoke1 = method2.invoke(o, "张三");
        System.out.println(invoke1);
        System.out.println("----------------------------------");

        //获取私有方法对象
        Method method = aClass.getDeclaredMethod("method", String.class, int.class);
        System.out.println(method);
        //让私有方法执行
        //取消语法检测
        method.setAccessible(true);
        Object invoke2 = method.invoke(o, "李四", 24);
        System.out.println(invoke2);
    }
}

在这里插入图片描述

动态代理

  1. 概述:是一种设计模式,可以在不修改源代码的情况下,对功能进程增强,使用前提是要有接口,否则无法进行动态代理;在程序运行期间,通过反射生成代理对象
  2. 代理类:Proxy
    static Object newProxyInstance (ClassLoader loader, Class < ?>[]interfaces, InvocationHandler h):返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序
package org.westos2.demo5;

public interface User {
    //添加用户
    void insert();
}
package org.westos2.demo5;

public class UserImpl implements User{
    @Override
    public void insert() {
        System.out.println("添加用户");
    }
}
package org.westos2.demo5;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyUtils {
    public static User getProxy(User user){
        User o = (User) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), new InvocationHandler() {
            Object invoke = null;
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //目标对象的方法一执行,这个invoke方法就会执行
                if (method.getName().equals("insert")) {
                    System.out.println("增加的功能1");
                    invoke = method.invoke(user);
                    System.out.println("增加的功能2");
                }
                return invoke;
            }

        });
        return o;
    }
}
package org.westos2.demo5;

public class MyTest {
    public static void main(String[] args) {
        UserImpl user = new UserImpl();
        //获取代理对象
        User proxy = ProxyUtils.getProxy(user);
        proxy.insert();
    }
}

在这里插入图片描述
动态代理是反射的一种应用,可以根据个人需求不断增强功能,对代码的扩展很实用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值