大佬,到底什么是Java的反射?

大佬,到底什么是Java的反射?什么是反射 JAVA 反射机制是在运行状态中 对于任何一个类 都能够知道这个类的所有属性和方法 对于任何一个对象 都能够调用它的任意方法和属性 这种动态获取信息以及动态调用对象方法的功能称为 java 语言的反射机制一般情况下 我们使用类来创建对象都是一开始就知道具体的类型以及类的用途 直接通过类来创建对象 Orderorder newOrder newBigDecima 4 32 order getPrice 而反射是一开始不知道我需要初始化的类是什么 到实际运行的时候才知道具体的类

什么是反射

JAVA反射机制是在运行状态中,对于任何一个类,都能够知道这个类的所有属性和方法;对于任何一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制

一般情况下,我们使用类来创建对象都是一开始就知道具体的类型以及类的用途,直接通过类来创建对象

Order order = new Order(new BigDecimal(4.32)); order.getPrice(); 

而反射是一开始不知道我需要初始化的类是什么,到实际运行的时候才知道具体的类型,此时只能通过反射的API来创建对象

Class clazz = Class.forName("org.kxg.reflection.Order"); Method method = clazz.getMethod("getPrice"); Constructor constructor = clazz.getConstructor(BigDecimal.class); Object object = constructor.newInstance(new BigDecimal(4.4)); method.invoke(object); 

上面两种方式的效果是一样的,都是创建了Order对象,调用Order对象的getPrice()方法,只不过一个是普通调用、一个是反射调用

所以简单来说,反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法

为什么需要反射

Java在不同的时期可以分成两种编译类型:

  • 静态编译:就是我们常用的方式,在编译时就确定的类型
  • 动态编译:在编译时无法确认类型,到运行才确定类型

动态编译发挥了Java的灵活性,体现了多态的应用,可以减低类之间的耦合性

Java反射是Java被视为动态语言的一个关键性质。

这个机制允许程序在运行时通过反射取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public、static等)、superclass(例如Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods。

反射可以在运行时加载、探知、使用编译期间完全未知的classes。

即Java程序可以加载一个运行时才得知名称的class,获取其完整构造,并生成其对象实体、或对其fields设值、或唤起其methods

反射是为了解决什么问题?

一句话概括就是使用反射可以赋予jvm动态编译的能力,否则类的元数据信息只能用静态编译的方式实现,例如热加载,Tomcat的classloader等等都没法支持

反射常用API

1、反射获取Class对象

//方式一:通过Class.forName()获取Class Class c1 = Class.forName("org.kxg.reflection.Order"); //方式二:使用.class方法 Class c2 = Order.class; //方式三:通过getClass()方法 Order o = new Order(new BigDecimal(1)); Class c3 = o.getClass(); 

2、通过反射创建类对象

//方式一:通过Class对象的newInstace()方法创建对象 Class c1 = Class.forName("org.kxg.reflection.Order"); Order o1 = (Order) c1.newInstance(); //方式二:通过Constructor对象的newInstance()方法创建对象 Class c2 = Order.class; Constructor constructor = c2.getConstructor(Order.class); Order o2 = (Order) constructor.newInstance(); 

3、获取类的属性

Order o = new Order(new BigDecimal(1)); Class c3 = o.getClass(); //只能获取除私有以外的属性 Field[] fields = c3.getFields(); //获取所有属性 Field[] fields1 = c3.getFields(); 

4、获取类方法

Order o = new Order(new BigDecimal(1)); Class c3 = o.getClass(); Method[] methods = c3.getMethods(); 

5、获取注解

Order o = new Order(new BigDecimal(1)); Class c3 = o.getClass(); Annotation[] annotations = c3.getAnnotations(); 

反射实现动态代理

实现方式:利用Java的反射机制,在java.lang.reflect 包下提供了Proxy类和InvocationHandler 接口来实现动态代理

下面以增加日志的需求来演示一下JDK动态代理的用法

//抽象对象 public interface CustService { 
    public void editCust(); } //真实对象 public class CustServiceImpl implements CustService { 
    public void editCust() { 
    System.out.println("edit cust ----"); } } //日志对象 public class LogService { 
    public void addLog(){ 
    System.out.println("add log ----"); } } //动态代理对象 public class JDKProxyCustService implements InvocationHandler { 
    private Object target; private LogService logService = new LogService(); public JDKProxyCustService(Object target){ 
    this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
    String methodName = method.getName(); System.out.println("methodName:" + methodName ); logService.addLog(); Object o = method.invoke(target,args); logService.addLog(); return o; } } //测试 public class TestJDKProxy { 
    public static void main(String[] args){ 
    CustService custService = new CustServiceImpl(); Class c = custService.getClass(); ClassLoader classLoader = c.getClassLoader();//目标对象的类加载器 Class[] interfaces = c.getInterfaces();//目标对象实现的所有接口 InvocationHandler h = new JDKProxyCustService(custService);//获取一个InvocationHandler,并将custService对象传入 / * 参数说明: * 1.classLoader表示目标对象的类加载器 * 2.interfaces表示目标对象实现的所有接口 * 3.InvocationHandler接口的实现 */ CustService proxy = (CustService) Proxy.newProxyInstance(classLoader,interfaces,h); proxy.editCust(); } } 运行结果: methodName:editCust add log ---- edit cust ---- add log ---- 

每个动态代理类(JDKProxyCustService)都必须实现InvocationHandler接口,当我们通过代理对象调用方法时,调用会被转到InvocationHandler接口的invoke方法。

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; 

实际上,真正有用的代码是:

Object o = method.invoke(target,args); 
CustService proxy = (CustService) Proxy.newProxyInstance(classLoader,interfaces,h); 

还有这句:

InvocationHandler h = new JDKProxyCustService(custService); 

传入需要代理的真实对象,实现调用的就是真实对象的方法

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/232497.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • ScriptManager.RegisterStartupScript方法[通俗易懂]

    ScriptManager.RegisterStartupScript方法[通俗易懂]出处:忘记了,致歉作者 如果页面中不用Ajax,cs中运行某段js代码方式可以是:Page.ClientScript.RegisterStartupScript(Page.GetType(),””,”window.open(‘default2.aspx’)”);如果页面中使用了Ajax,则上述代码即使执行也无效果。对这种情况我们通常采用:ScriptManag

    2022年7月13日
    14
  • 双拼输入法快速入门

    双拼输入法快速入门转自少数派https://sspai.com/post/32809,作者@大唐废猫本文适合并仅适合以下人群观看:喜爱折腾熟练使用盲打对汉语拼音有敏感度对于输入速度有要求愿意慢慢看完这一大篇文章并坚持痛苦使用为什么要批判全拼输入?自从计算机发明之后,如何利用QWERTY键盘输入汉字便成为一大难题,在历经五笔、注音、双拼、手写等各类输入角逐后,全拼…

    2022年6月18日
    49
  • pycharm代码运行不显示结果_pycharm运行配置错误

    pycharm代码运行不显示结果_pycharm运行配置错误我最近看了两节关于数据分析的课程,其中最基础也最重要的知识就是支持度,置信度和提升度了。而在打印提升度的相关信息时,我遇到了一些麻烦!老师用的是JupyterNotebook来演示,而我用的是pycharm(其实跟编译器没关系),然后打印提升度时我发现有很多数据我无法打印出来!只是给我留了半串省略号…我就纳闷了,到底是啥原因?shopping_basket={‘ID’:[1,2,3,4,5,6],’Basket’:[[‘Onion’,’Bee

    2022年8月29日
    3
  • 数论的概念_数论难吗

    数论的概念_数论难吗转载自:https://blog.csdn.net/whereisherofrom/article/details/78922798素数:http://www.cnblogs.com/fzl194/

    2022年8月2日
    12
  • CSS绘画三角形

    CSS绘画三角形本案例使用CSS绘画了一个三角形的图案。预览演示地址:https://tympanus.net/codrops-playground/SaraSoueidan/kFTn9yJk/editor将下面的代码复制到演示地址对应位置即可查看效果<!–HTML–><divclass="container"><divclass="eleme…

    2022年6月26日
    28
  • java深拷贝的实现方式_接口可以创建对象吗

    java深拷贝的实现方式_接口可以创建对象吗Cloneable接口与Serializable接口都是定义接口而没有任何的方法。Cloneable可以实现对象的克隆复制,Serializable主要是对象序列化的接口定义。很多时候我们涉及到对象的复制,我们不可能都去使用setter去实现,这样编写代码的效率太低。JDK提供的Cloneable接口正是为了解决对象复制的问题而存在。Cloneable结合Serializable接口可以实现JVM对象的深度复制。

    2022年10月14日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号