Java反射、代理机制

这篇具有很好参考价值的文章主要介绍了Java反射、代理机制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.什么是反射

官方解释:反射允许对封装类的字段、方法和构造方法的信息进行编程访问。

虚拟机加载类文件后,会在方法区生成一个类对象,包含了类的结构信息,如字段、方法、构造方法等。反射是一种能够在程序运行时动态访问、修改类对象中任意属性的机制(包括private属性)。

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

如果说大家研究过框架的底层原理或者咱们自己写过框架的话,一定对反射这个概念不陌生。

反射之所以被称为框架的灵魂,主要是因为它赋予了我们在运行时分析类以及执行类中方法的能力。

通过反射你可以获取任意一个类的所有属性和方法,你还可以调用这些方法和属性。

获取类对象的四种方式


1.通过对象获取到类对象.getClass();
Class personClass = person.getClass();
2.通过 Class.forName()传入类的全路径获取;装入类,并做类的静态初始化,返回Class的对象
Class personClass = Class.forName("全类名");
3.通过类属性 ClassName.Class获取类对象;
Class personClass = Person.Class;
4.通过ClassLoader.getSystemClassLoader().loadClass("全类名");通过类加载器获取 Class 对象不会进行初始化,意味着不进行包括初始化等一系列步骤,静态代码块和静态对象不会得到执行

注意:全类名是包名+类名,一般是程序src目录下的包名+类名。

类对象中描述各个部分的对象:

  1. Class:描述整个类的对象
  2. Constructor:描述构造方法的对象
            Class clazz = Class.forName("Person");
            //获取类的所有构造方法
            Constructor[] constructorAll = clazz.getDeclaredConstructors();
            for(Constructor c: constructorAll){
                System.out.println(c);
            }
    
            Constructor constructor1 = clazz.getDeclaredConstructor();
            Constructor constructor2 = clazz.getDeclaredConstructor(String.class);
            System.out.println(constructor1);
            System.out.println(constructor2);
    
            //可以获取构造方法中的一些内容
            int modifiers = constructor1.getModifiers();
            System.out.println(modifiers);
    
            int parameterCount = constructor1.getParameterCount();
            System.out.println(parameterCount);
    
            Parameter[] parameters = constructor2.getParameters();
            for(Parameter p: parameters){
                System.out.println(p);
            }
    
            //使用构造方法创建对象
            Person person = (Person) constructor1.newInstance();
            System.out.println(person);
  3. Field:描述成员变量的对象
            Class clazz = Class.forName("Person");
            //获取私有/非私有属性
            Field[] fields = clazz.getDeclaredFields();
            for(Field f: fields){
                System.out.println(f);
            }
    
            Field field = clazz.getDeclaredField("name");
            System.out.println(field);
    
            //获取权限修饰符
            int modifiers = field.getModifiers();
            System.out.println(modifiers);
    
            //获取数据类型
            String value = field.getName();
            System.out.println( value);
    
  4. Method:描述成员方法的对象。

2.反射的功能

1.获取一个类里面所有的信息和其他业务逻辑。

2.结合配置文件,动态的创建对象并调用方法。

1、Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。

2、Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。

3.序列化、反序列化

Serialization(序列化)是一种将对象以一连串的字节描述的过程;反序列化deserialization是一种将这些字节重建成一个对象的过程。将程序中的对象,放入文件中保存就是序列化,将文件中的字节码重新转成对象就是反序列化。

ObjectOutputStream 类用来序列化一个对象,可将对象序列化到一个文件中。

注意: 当序列化一个对象到文件时, 按照 Java 的标准约定是给文件一个 .ser 扩展名。


public class Main {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //创建文件输出流对象
        FileOutputStream fileOutputStream = new FileOutputStream("D:\\Serializable\\Person.ser");
        //创建序列化对象
        Person person = new Person("name",22,"女","black","boy");
        //创建对象输出流
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        //将对象序列化
        objectOutputStream.writeObject(person);
        //创建文件输入流对象
        FileInputStream fileInputStream = new FileInputStream("D:\\Serializable\\Person.ser");
        //创建对象输入流
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
        //反序列化
        Person person1 = (Person) objectInputStream.readObject();
        System.out.println(person1);
    }
}

三、序列化和反序列化的注意点:

1.序列化时,只对对象的属性进行保存。

2.当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口。

3.当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化。

4.声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态,transient代表对象的临时数据。

5.Java有很多基础类已经实现了serializable接口,比如String,Vector等。但是也有一些没有实现serializable接口的。

6.序列号id,用于标识序列号对象的版本,在反序列化的过程中,会使用序列化id来检查序列化对象的版本与当前类的版本是否匹配。

功能

  • 对象随着程序的运行而创建,程序结束对象就销毁,序列化可以让对象持久的保持在内存中

  • 可以在进程之间进行对象传输

4.动态代理

无侵入的为对象的方法增加新功能。

动态代理的实现步骤:

  1. 定义接口,并定义要在代理对象中实现的方法(包括返回类型、参数列表、方法名)
  2. 创建一个实现InvocationHandler接口的类,并重写invoke方法,invoke方法在代理对象调用方法时触发,并允许在方法调用前后增加额外的逻辑。
  3. 使用Proxy类创建代理对象java.lang.reflect.Proxy类的静态方法newProxyInstace来创建代理对象,该方法有三个参数。参数1:加载代理类的类加载器;参数2:目标对象实现的接口;参数3:InvocationHandler对象,表示实现invoke方法的对象。
  4. 调用代理对象的方法,当代理对象的方法被调用时,invoke方法会被触发。

public class Person implements IPerson{
    private String name;

    public Person(){

    }

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

    @Override
    public String eat(String thing){
        System.out.println(this.name+"正在吃"+thing);
        return thing;
    }

    @Override
    public void run(){
        System.out.println(this.name+"正在run");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public interface IPerson {
    //把需要代理的方法定义在接口当中
    public abstract String eat(String name);
    public abstract void run();
}

public class ProxyUtil {
    /**
     *为给定的对象生成一个代理对象
     * @param person
     */
    public static IPerson createProxy(Person person) {
        /**
         * 参数1:指定类加载器,去加载生成的代理类
         * 参数2:指定接口,这个接口用于指定生成的代理长什么,也就是有哪些方法
         * 参数3:用来指定生成的代理对象要干什么事情
         */

        IPerson iPerson = (IPerson) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader()
                , new Class[]{IPerson.class}, new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        /**
                         * 参数1:代理的对象
                         * 参数2:要运行的方法
                         * 参数3:调用方法时传递的实参
                         */
                        if("eat".equals(method.getName())){
                            System.out.println("拿筷子");
                            System.out.println("拿碗");
                        }else if("run".equals(method.getName())){
                            System.out.println("带水");
                            System.out.println("穿裤子");
                        }

                        return method.invoke(person,args);
                    }
                });
        return iPerson;
    }
}

  实现原理:通过代理类生成字节码文件,使用类加载器将文件加载到内存,最终创建代理对象。

注意:动态的生成字节码文件,是在运行时发生的。                                                                                                                                                                            文章来源地址https://www.toymoban.com/news/detail-690513.html

到了这里,关于Java反射、代理机制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java反射和动态代理

    反射允许对封装类的成员变量、成员方法和构造方法的信息进行编程访问 成员变量:修饰符、名字、类型、get/set值 构造方法:修饰符、名字、形参、创建对象 成员方法:修饰符、名字、形参、返回值、抛出的异常、获取注解、运行方法 获取class对象 Class.forName(“全类名”

    2024年02月03日
    浏览(56)
  • Java安全基础之Java反射机制和ClassLoader类加载机制

    目录 Java 反射机制 反射 java.lang.Runtime ClassLoader 类加载机制 URLClassLoader loadClass() 与 Class.forName() 的区别? Java 反射(Reflection)是 Java 非常重要的动态特性。在运行状态中,通过 Java 的反射机制,我们能够判断一个对象所属的类。了解任意一个类的所有属性和方法。能够调用任

    2024年04月22日
    浏览(40)
  • Java的反射机制(2)

    目录 Class类基本介绍 Class类的常用方法 如何获取class类对象 哪些类型有Class对象 Class类基本介绍 在Java语言中,每个对象都有一个运行时类,即其所属的类。而这个运行时类在Java中是以Class类的实例形式存在的,该Class类实例就是所谓的Class对象。Class类表示一个类或接口的元

    2024年02月08日
    浏览(39)
  • Java的反射机制

    Java 的反射机制允许在程序运行期间,借助反射 API 获取类的内部信息,并能直接操作对象的内部属性及方法。 Java 反射机制提供的功能: 在运行时,使用反射分析类的能力,获取有关类的一切信息(类所在的包、类实现的接口、标注的注解、类的数据域、类的构造器、类的

    2024年02月02日
    浏览(41)
  • Java反射机制是什么?

    Java 反射机制 是 Java 语言的一个重要特性。 在学习 Java 反射机制前,大家应该先了解两个概念,编译期和运行期。 编译期 是指把源码交给编译器编译成计算机可以执行的文件的过程。在 Java 中也就是把 Java 代码编成 class 文件的过程。编译期只是做了一些翻译功能,并没有把

    2024年02月12日
    浏览(38)
  • Java反射机制深入详解

    一.概念 反射就是把Java的各种成分映射成相应的Java类。 Class类的构造方法是private,由JVM创建。 反射是java语言的一个特性,它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作。例如它允许一个java的类获取他所有的成员变量和方法并且显示

    2024年02月06日
    浏览(45)
  • 【JavaSE】Java的反射机制

    1.java反射机制 1.1简介 被视为动态语言的关键,允许程序在执行期间,借助于RefectionAPI取得任何类的内部信息。在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个类对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方

    2024年04月26日
    浏览(41)
  • Java重点:反射机制的使用

    目录 一、概念 二、类类 1、类类的获取方式 1)类名.Class 2)对象.getClass() 3)Class.forName() 三、反射实例化 1、调用一个公有的无参构造方法 2、调用一个公有的一个参构造方法 3、调用一个公有的两个参构造方法 4、调用一个私有的一个参构造方法 四、反射:方法调用 1、公有

    2024年02月07日
    浏览(42)
  • Java学习路线(23)——反射机制

    一、概述 (一)什么是反射: 反射指的是任何一个Class类,在“运行时”都可以直接得到全部成分。 (二)动态可获取的对象: 构造器对象——Constructor,成员变量对象——Field,成员方法对象——Method。 (三)反射关键: 第一步都是得到编译后的Class对象,然后可以获得

    2024年02月08日
    浏览(44)
  • 【Java基础】深入理解反射、反射的应用(工厂模式、代理模式)

    Java 反射机制是指在 运行时动态地获取和操作类的信息、调用对象的方法和访问对象的属性的能力 。通过反射,可以在程序运行时分析和修改类的结构、行为和状态。 Java 反射机制提供了以下功能: 获取类的信息:可以获取类的名称、修饰符、父类、实现的接口等。 创建对

    2024年02月09日
    浏览(60)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包