反射技术

本文详细介绍了Java反射机制的基本概念及应用,包括如何通过反射获取类的构造方法、成员变量和方法,并进行操作。此外,还探讨了动态代理的原理与实现方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

反射技术

一、反射概述

1. 反射机制

    *  指的是可以于运行时加载、探知、使用编译期间完全未知的类。 

    *  程序在运行状态中,可以动态加载一个只有名称的类,对于任意一个 已加载的类,都能够知道这个类的所有属性和方法;对于任意一个对 象,都能够调用它的任意一个方法和属性;

    *  加载完类之后,在堆内存中,就产生了一个 Class 类型的对象(一个 类只有一个 Class 对象),这个对象就包含了完整的类的结构信息。 我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过 这个镜子看到类的结构,所以,我们形象的称之为:反射。 

2. Class类介绍

    *   java.lang.Class类十分特殊,用来表示java中类型 (class/interface/enum/annotation/primitive type/void)本 身。 

    *   Class类的对象包含了某个被加载类的结构。一个被加载的类对应一个 Class对象。 

    *  当一个class被加载,或当加载器(class loader)的defineClass()被 JVM调用,JVM 便自动产生一个Class 对象。 

    *  Class类是Reflection的根源。针对任何您想动态加载、运行的类,唯有先获得相应的Class 对象

Class的三种获取方式

        * a:Object类的getClass()方法,判断两个对象是否是同一个字节码文件

        * b:静态属性class,锁对象

        * c:Class类中静态方法forName(),读取配置文件

二、通过反射获取带参构造方法并使用

 Java Code 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

 

public class Demo3_Constructor {

    
/**
     * Class类的newInstance()方法是使用该类无参的构造函数创建对象, 如果一个类没有无参的构造函数,
     * 就不能这样创建了,可以调用Class类的getConstructor
     * (String.class,int.class)方法获取一个指定的构造函数然后再调用Constructor类的newInstance
     * ("张三",20)方法创建对象
     * @throws Exception 
     */

    public static void main(String[] args) throws Exception {
        Class clazz = Class.forName(
"cn.wj.bean.Person");
        
//Person p = (Person) clazz.newInstance();              通过无参构造创建对象
        //System.out.println(p);
        Constructor c = clazz.getConstructor(String.class,int.class);   //获取有参构造
        Person p = (Person) c.newInstance("张三",23);                     //通过有参构造创建对象
        System.out.println(p);
    }

}

三、通过反射获取成员变量并使用

 Java Code 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

 

public class Demo4_Field {
    
/**
     * Class.getField(String)方法可以获取类中的指定字段(可见的),
     * 如果是私有的可以用getDeclaedField("name")方法获取,通过set(obj, "李四")方法可以设置指定对象上该字段的值,
     * 如果是私有的需要先调用setAccessible(true)设置访问权限,用获取的指定的字段调用get(obj)可以获取指定对象中该字段的值
     * @throws Exception 
     */

    public static void main(String[] args) throws Exception {
        Class clazz = Class.forName(
"cn.wj.bean.Person");
        Constructor c = clazz.getConstructor(
String.class,int.class);   //获取有参构造
        Person p = (Person) c.newInstance("张三",23);                     //通过有参构造创建对象
        
        
//Field f = clazz.getField("name");                             //获取姓名字段
        //f.set(p, "李四");                                               //修改姓名的值
        Field f = clazz.getDeclaredField("name");                       //暴力反射获取字段
        f.setAccessible(true);                                          //去除私有权限
        f.set(p, "李四"); 
        
        System.out.println(p);
    }

}

 

四、通过反射获取方法并使用

 

 Java Code 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

 

public class Demo5_Method {
    
/**
     * Class.getMethod(String, Class...) 和 Class.getDeclaredMethod(String,
     * Class...)方法可以获取类中的指定方法,调用invoke(Object,
     * Object...)可以调用该方法,Class.getMethod("eat") invoke(obj)
     * Class.getMethod("eat",int.class) invoke(obj,10)
     * @throws Exception 
     */

    public static void main(String[] args) throws Exception {
        Class clazz = Class.forName(
"com.heima.bean.Person");
        Constructor c = clazz.getConstructor(
String.class,int.class);   //获取有参构造
        Person p = (Person) c.newInstance("张三",23);                     //通过有参构造创建对象
        
        Method m = clazz.getMethod(
"eat");                              //获取eat方法
        m.invoke(p);
        
        Method m2 = clazz.getMethod(
"eat"int.class);                  //获取有参的eat方法
        m2.invoke(p, 10);
    }

}

 

五、动态代理的概述和实现

 

1,概述

1)代理:本来应该自己做的事,请了别人来做,被请的人就是代理对象

2)动态代理:在程序运行过程中产生的这个对象,而程序运行过程中产生对象其实就是我们刚才反射讲解的内容,所以,动态代                         理其实就是通过反射来生成一个代理

2,实现

       * 在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动            态代理对象。
* JDK提供的代理只能针对接口做代理。我们有更强大的代理cglib,Proxy类中的方法创建动态代理类对象
* public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
* 最终会调用InvocationHandler的方法
* InvocationHandler Object invoke(Object proxy,Method method,Object[] args)

MyInvocationHandler:

 Java Code 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

 

public class MyInvocationHandler implements InvocationHandler {
    
private Object target;
    
    
public MyInvocationHandler(Object target) {
        
this.target = target;
    }
    @Override
    
public Object invoke(Object proxy, Method method, Object[] args)
            
throws Throwable {
        System.out.println(
"权限校验");
        method.invoke(target, args);                    
//执行被代理target对象的方法
        System.out.println("日志记录");
        
return null;
    }

}

Test类:

 Java Code 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

 

public class Test {

    
/**
     * @param args
     */

    public static void main(String[] args) {
    
        StudentImp si = 
new StudentImp();
        si.login();
        si.submit();
        
        System.out.println(
"-------------------------------");
        MyInvocationHandler m = 
new MyInvocationHandler(si);
        Student s = (Student)Proxy.newProxyInstance(si.getClass().getClassLoader(), si.getClass().getInterfaces(), m);
        
        s.login();
        s.submit();
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值