Java反射技术

反射机制

        Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,这种动态获取状态信息以及调用对象方法的功能称为Java语言的反射机制。简单来说,反射机制指的是程序在运行时能够获取自身的信息。在java中,只要给定类的名字,就可以通过反射机制来获得类的所有信息。

基本的反射技术

Class类

在反射中只要我们获取了一个类的Class对象,我们就可以获取该类的所有信息,在Java中获取Class对象的方法有三种:

1.对象名.getClass();  通过实例化对象的getClass()方法进行获取。

String str = new String();
Class cls = str.getClass();

2.类名.class; 用过类名的class方法进行获取

Class cls = String.class;

3.Class.forName();通过Class的forName()方法进行获取,参数为类的完全限定名

Class cls = Class.forName("java.lang.String");

调用构造方法

为了能够任意调用类的构造方法,Java的反射API提供了Construcor对象,该对象包含了一个构造方法的所有信息,但在调用构造方法之前,我们首先得获取该类的构造方法,部分实现代码如下:

public class Main {
    public static void main(String[] args) throws Exception {
        //获取String类的Class对象
        Class cls = Class.forName("java.lang.String");

        // 获取构造方法String(String):
        Constructor cons = cls.getConstructor(String.class);
        
        // 调用构造方法:
        String str = (String) cons.newInstance("hello world");
        System.out.println(str);

    }
}

获取继承关系

当我们获取到某个Class对象时,那么我们就可以通过下列方法获取该类的继承关系,部分实现代码如下:

Class cls = Class.forName("java.lang.String");//获取String类的Class对象
Class superClass = cls.getSuperclass();//获取该类父类类型
Class[] interfaces = cls.getInterfaces();//获取该类的所有接口

访问字段

对于一个类中的字段,我们不仅可以通过Class对象获取该字段值,还可以对字段值进行修改,部分实现代码如下:

import java.lang.reflect.Field;

public class Main {

    public static void main(String[] args) throws Exception {
        //通过Person类中的get方法获取字段值
        Person person = new Person("Xiao Ming");
        System.out.println(person.getName()); // "Xiao Ming"
        
        //通过反射获取字段值
        Class cls = p.getClass();
        Field filed = cls.getDeclaredField("name");
        
        //由于name字段被private修饰,因此需要通过setAccessible(true)将name字段设置为允许访问
        filed.setAccessible(true);
        filed.set(person, "Xiao Hong");
        
        System.out.println(person.getName()); // "Xiao Hong"
    }
}

class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }
}

调用方法

当我们获取到某个Class对象时,那么我们就可以通过下列方法实现方法的调用,部分实现代码如下:

public class Main {
    public static void main(String[] args) throws Exception {
        // String对象:
        String s = "Hello world";
        
        // 获取String substring(int)方法,参数为int:
        Method m = String.class.getMethod("substring", int.class);
        
        // 在s对象上调用该方法并获取结果:
        String r = (String) m.invoke(s, 6);
        
        // 打印调用结果:
        System.out.println(r);
    }
}

反射的功能

在运行期构造一个类的对象;

获取方法、属性等类中的基本信息;

调用类对象的方法;生成动态代理。

动态代理

动态代理是代理模式的一种实现方式,代理模式除了动态代理还有 静态代理,只不过静态代理能够在编译时期确定类的执行对象,而动态代理只有在运行时才能够确定执行对象是谁。代理可以看作是对最终调用目标的一个封装,我们能够通过操作代理对象来调用目标类,这样就可以实现调用者和目标对象的解耦合。

代理模式所涉及的角色有三个:
(1)、抽象主题角色(Subject):声明了真实主题和代理主题的公共接口,这样一来在使用真实主题的任何地方都可以使用代理主题。
(2)、代理主题角色(Proxy):代理主题角色内部含有对真实主题的引用,从而可以操作真实主题对象;代理主题角色负责在需要的时候创建真实主题对象;代理角色通常在将客户端调用传递到真实主题之前或之后,都要执行一些其他的操作,而不是单纯地将调用传递给真实主题对象。
(3)、真实主题角色(RealSubject):定义了代理角色所代表的真实对象。
附:在WCF或者WebService的开发过程中,我们在客户端添加服务引用的时候,在客户程序中会添加一些额外的类,在客户端生成的类扮演着代理主题角色,我们客户端也是直接调用这些代理角色来访问远程服务提供的操作。这个是远程代理的一个典型例子。

动态代理在mybatis中的应用

在项目中配置Mybatis时,我们仅创建了映射器接口映射文件,并未创建映射器接口的实现类,但当我们使用Sqlsesion的getMapper()方法时,Mybatis却自动帮我们实现了映射器接口的实现类,从而可以使用映射器接口中的方法。

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值