当前位置:首页 > Java技术 > java反射机制原理,为什么需要反射,反射的作用

java反射机制原理,为什么需要反射,反射的作用

2022年09月17日 08:45:03Java技术6

最近在学java反射以及动态代理,好多博客都写的十分官方。就自己整合些资料。加深java反射机制的理解。

在说反射之前,我们要先了解动态语言和静态语言的概念:

动态类型语言

所谓动态类型语言,就是类型的检查是在运行时才做。
动态类型在解释语言中极为普遍,如 JavaScript、Perl、Python、Ruby 等等

静态类型语言

静态类型语言的类型检查是在运行前的编译阶段,比如 C#、Java 等都是静态类型语言,静态类型语言为了达到多态会采取一些类型鉴别手段,如继承、接口,而动态类型语言却不需要

注意:但是JAVA有着一个非常突出的动态相关机制——Reflection(反射),用在Java身上指的是可以于运行时加载、探知、使用编译期间完全知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class获悉其完整构造(但不包括methods定义),并生成其对象例(newInstance)或对其fields设值,或唤起(invoke)其methods方法。

什么叫反射机制?

反射机制是在运行状态中:

  • 对于任意一个类,都能够知道这个类的所有属性和方法。
  • 对于任意一个对象,都能够调用它的任意一个方法和属性。

反射的应用

我们可能听过,Java编写的程序,一次编译,到处运行。这也是Java程序为什么是无关平台的所在,原因在于,java的源代码会被编译成.class文件字节码,只要装有Java虚拟机JVM的地方(Java提供了各种不同平台上的虚拟机制。).class文件才可以在运行加载。

  • 第一步:由Java编译器进行源代码编译,得到相应类的字节码.class文件。
  • 第二步:生成class文件之后,通过ClassLoader类加载器加载进内存,Java字节码由JVM执行解释给目标计算机。
  • 第三步,目标计算机将结果呈现给我们计算机用户;因此,Java并不是编译机制,而是解释机制.class文件才可以在不同平台上运行加载。

java反射机制原理,为什么需要反射,反射的作用 _ JavaClub全栈架构师技术笔记
Java的反射机制,操作的就是这个.class文件,首先加载相应类的字节码(运行编译器idea的时候,.class文件的字节码会加载到内存中),随后解剖(反射 reflect)出字节码中的构造函数、方法以及变量(字段),或者说是取出,我们先来定义一个类Person,里面定义一些构造函数,方法,以及变量:

package com.ztb.entity;
public class Person {
     
    private int age;
    private String name;
    /**
     * 有参构造器
     * @param name
     * @param age
     */
    public Person( String name,int age) {
     
        this.age = age;
        this.name = name;
    }
    /**
     * 无参构造器
     */
    public Person() {
     
    }
    //公有 有参方法
    public void public_show(String str,int i)
    {
     
        System.out.println("public show "+str+"..."+i);
    }
    //公有 无参方法
    public void public_prin()
    {
     
        System.out.println("公有无参代码块。。。。");
    }
    //私有 有参方法
    private void private_show(String str,int i)
    {
     
        System.out.println("私有有参代码块:private show "+str+"..."+i);
    }
    //私有 无参方法
    private void private_prin()
    {
     
        System.out.println("私有无参方法代码块:private prin");
    }
}

新建测试类TestClass

  //获取字节码文件中 方法 再取出其公有方法
        String classname = "com.ztb.entity.Person";//必须是全路径类名
        //寻找名称的类文件,加载进内存 产生class对象
        Class cl = Class.forName(classname);
        //获取一个Person对象
        System.out.println("获取一个Person对象:");
        Object obj=cl.newInstance();
        System.out.println();

        //1.获取 公有 无参方法  public void public_prin()
        Method Person_public_prin=cl.getMethod("public_prin",null);
        System.out.println("获取执行 public void public_prin ()方法:");
        Person_public_prin.invoke(obj,null);//obj 是这个类的实例
        System.out.println();

        //2.获取 公有 有参方法 public void public_show(java.lang.String,int)
        Method Person_public_show=cl.getMethod("public_show",String.class,int.class);
        System.out.println("获取执行 public void public_show(java.lang.String,int) :");
        Person_public_show.invoke(obj,"神奇的公有有参构造方法下的我",12);
        System.out.println();

        //3.获取 私有 无参方法  private void private_show()
        Method Person_private_prin=cl.getDeclaredMethod("private_prin",null);
        Person_private_prin.setAccessible(true);
        System.out.println("获取执行  private void private_show():");
        Person_private_prin.invoke(obj,null);
        System.out.println();

        //4.获取私有有参方法  private_prin(java.lang.String,int)
        Method Person_private_show=cl.getDeclaredMethod("private_show",String.class,int.class);
        Person_private_show.setAccessible(true);
        System.out.println("获取执行 private void demo2.Person.private_show(java.lang.String,int) :");
        Person_private_show.invoke(obj,"神奇的私有有参构造方法下的我 :",23);
        System.out.println();

        /**
         * 获取所有已经声明的公有的方法或者私有方法
         */
        Method[] methods=cl.getDeclaredMethods();
        for (Method method: methods){
     
            System.out.println("方法名:"+method.getName()+"返回值类型:"+method.getGenericReturnType().getTypeName());
        }

    }

运行结果如图示:
java反射机制原理,为什么需要反射,反射的作用 _ JavaClub全栈架构师技术笔记
为什么new一个对象那么简单,非要用反射技术中的newInstance?
为什么,我可以直接对象a1. 变量访问变量,却非要用反射那么费劲的获得name字段呢?
为什么,我几行代码就能搞定的事情,非要用反射呢?

假设我们定义了很多类,有Animal、Person、Car… ,如果我想要一个Animal实例,那我就new Animal(),如果另一个人想要一个Person实例,那么他需要new Person(),当然,另一个说,我只要一个Car实例,于是它要new Car()…这样一来就导致,每个用户new的对象需求不相同,因此他们只能修改源代码,并重新编译才能生效。这种将new的对象写死在代码里的方法非常不灵活,因此,为了避免这种情况的方法,Java提供了反射机制,典型的应用如下:
java反射机制原理,为什么需要反射,反射的作用 _ JavaClub全栈架构师技术笔记

我们知道Spring的IOC,即“控制反转”(通过第三方配置文件实现对 对象的控制)。简单说是将我们设计好的对象交给容器控制,而不是直接交给程序内部进行对象的控制。

比如,在Spring中,我们经常看到:
java反射机制原理,为什么需要反射,反射的作用 _ JavaClub全栈架构师技术笔记

针对上述的配置,我们Spring是怎么帮助我们实例化对象,并放到容器中去了呢? 没错,就是通过反射!!!!

我们看下,下面的伪代码实现过程:

java
//解析<bean .../>元素的id属性得到该字符串值为"sqlSessionFactory" 
	    String idStr = "sqlSessionFactory";  
	    //解析<bean .../>元素的class属性得到该字符串值为"org.mybatis.spring.SqlSessionFactoryBean"  
	    String classStr = "org.mybatis.spring.SqlSessionFactoryBean";  
	    //利用反射知识,通过classStr获取Class类对象  
	    Class cls = Class.forName(classStr);  
	    //实例化对象  
	    Object obj = cls.newInstance();  
	    //container表示Spring容器  
	    container.put(idStr, obj);  
		
	    //当一个类里面需要用另一类的对象时,我们继续下面的操作
	    
	    //解析<property .../>元素的name属性得到该字符串值为“dataSource”  
	    String nameStr = "dataSource";  
	    //解析<property .../>元素的ref属性得到该字符串值为“dataSource”  
	    String refStr = "dataSource";  
	    //生成将要调用setter方法名  
	    String setterName = "set" + nameStr.substring(0, 1).toUpperCase()  
	            + nameStr.substring(1);  
	    //获取spring容器中名为refStr的Bean,该Bean将会作为传入参数  
	    Object paramBean = container.get(refStr);  
	    //获取setter方法的Method类,此处的cls是刚才反射代码得到的Class对象  
	    Method setter = cls.getMethod(setterName, paramBean.getClass());  
	    //调用invoke()方法,此处的obj是刚才反射代码得到的Object对象  
	    setter.invoke(obj, paramBean);

我们经常提到的Java web框架中,里面就用到了反射机制,只要在代码或配置文件中看到类的完全限定名(包名+类名),其底层原理基本上使用的就是Java的反射机制。

获得反射入口的三种方式(获得类)

1).Class.forName(全类名)(推荐使用)

Class<?> classStu = Class.forName("reflect.Student");
		System.out.println(classStu);

2).类名.class

Class<?> classStu2 = Student.class;
	System.out.println(classStu2);

3).对象.getClass()

Student stu = new Student();
	Class<?> classStu3 = stu.getClass();
	System.out.println(classStu3);

作者:曾曾曾植树
来源链接:https://blog.csdn.net/weixin_43373417/article/details/106441638

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。


本文链接:https://www.javaclub.cn/java/42373.html

分享给朋友:

“java反射机制原理,为什么需要反射,反射的作用” 的相关文章

Java反射机制

  往往当我们面对一项新的知识时,我们往往需要知道三个方面,它是什么,它能做什么,它比原有知识强在哪里,我们该怎么使用它。当你能够解决这些问题时,便意味着你已经对这项知识入门了。 一、是什么   Java Reflaction in Action有这么一句话,可以解释。反射...

java面试题--java反射机制

Java反射机制的作用: 1)在运行时判断任意一个对象所属的类。 2)在运行时判断任意一个类所具有的成员变量和方法。 3)在运行时任意调用一个对象的方法 4)在运行时构造任意一个类的对象 拓展: 1、什么是反射机制?...

Java 反射之Class介绍和三种创建方式

反射的好处(为什么需要反射机制): 通过反射机制可以获取到一个类的完整信息,例如:所有(包含private修饰)属性和方法,包信息等。 换句话说,Class本身表示一个类的本身,通过Class可以完整获取一个类中的完整结构,包含此...

浅谈Java反射的实现原理

从一段示例代码开始 Class clz = Class.forName("ClassA"); Object instance = clz.newInstance(); Method method =...

JAVA利用反射映射JSON对象为JavaBean

关于将JSONObject转换为JavaBean,其实在JSONObject中有对于的toBean()方法来处理,还可以根据给定的JsonConfig来处理一些相应的要求,比如过滤指定的属性 [java] vi...

java反射机制详解

java反射机制详解

一、什么是反射 JAVA反射机制是在运行状态中,对于任何一个类,都能够知道这个类的所有属性和方法;对于任何一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。 想要使用反射机制,就必须要先获取到该类的字节码文件对象(...

深入理解Java反射(通俗易懂)

深入理解Java反射(通俗易懂)

反射是框架设计的灵魂 (使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码))   一、反射的概述 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,...

java反射获取包下所有的类

引三方包 <dependency> <groupId>org.reflections</groupId> <artifactId>reflections</arti...

Java反射机制详解

作用   反射的定义:在运行状态中,能获取任意一个类的所有方法和属性;能调用一个对象的所有方法和属性。这种动态获取类信息和动态调用对象方法和属性的功能就是Java的反射机制。   注意定义中的措辞,是所有的方法和属性,即使是私有的也能调用。所以功能是非常强大的。但在我们日常...

java反射的使用场合和作用、及其优缺点

1)使用场合 在编译时根本无法知道该对象或类可能属于哪些类,程序只依靠运行时信息来发现该对象和类的真实信息。 2)主要作用 通过反射可以使程序代码访问装载到JVM 中的类的内部信息,获取已装载类的属性信息,获取已装载类的方法,获取已装载类的构造方法信息 3)反射...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。