谁来帮用通俗易懂的语言解释下java的反射机制_java吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:640,953贴子:
谁来帮用通俗易懂的语言解释下java的反射机制收藏
RT~~万分感谢,百度的内容都看不懂啊
智联招聘,每天更新350万高薪招聘java程序员信息,真实有效,24小时极速反馈,立即登录填写简历,快速找到好工作!
根据类名生成类的对象
登录百度帐号推荐应用Java的反射机制是什么,如何实现?
来源:it-home
本文和大家分享的是java语言/course/234/的反射机制及相关应用场景。其实JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的以及动态调用对象的方法的功能称为Java的反射机制。 反射机制提供了哪些功能? ·在运行时判定任意一个对象所属的类 ·在运行时构造任意一个类的对象; ·在运行时判定任意一个类所具有的成员变量和方法; ·在运行时调用任意一个对象的方法; ·生成动态代理; Java反射机制类: java.lang.C //类 java.lang.reflect.C//构造方法 java.lang.reflect.F //类的成员变量 java.lang.reflect.M//类的方法 java.lang.reflect.M//访问权限 Java反射机制实现: 1.)class对象的获取 //第一种方式 通过对象getClass方法 Person person = new Person();Class class1 = person.getClass();//第二种方式 通过类的class属性&/?& class1 = Person.class;try { //第三种方式 通过Class类的静态方法——forName()来实现 class1 = Class.forName("com.whoislcj.reflectdemo.Person"); } catch (ClassNotFoundException e) { e.printStackTrace(); } 2.)获取class对象的摘要信息 boolean isPrimitive = class1.isPrimitive();//判断是否是基础类型boolean isArray = class1.isArray();//判断是否是集合类boolean isAnnotation = class1.isAnnotation();//判断是否是注解类boolean isInterface = class1.isInterface();//判断是否是接口类boolean isEnum = class1.isEnum();//判断是否是枚举类boolean isAnonymousClass = class1.isAnonymousClass();//判断是否是匿名内部类boolean isAnnotationPresent = class1.isAnnotationPresent(Deprecated.class);//判断是否被某个注解类修饰 String className = class1.getName();//获取class名字 包含包名路径Package aPackage = class1.getPackage();//获取class的包信息 String simpleName = class1.getSimpleName();//获取class类名int modifiers = class1.getModifiers();//获取class访问权限 Class[] declaredClasses = class1.getDeclaredClasses();//内部类Class declaringClass = class1.getDeclaringClass();//外部类&/?&&/?& 3.)获取class对象的属性、方法、构造函数等 Field[] allFields = class1.getDeclaredFields();//获取class对象的所有属性 Field[] publicFields = class1.getFields();//获取class对象的public属性try { Field ageField = class1.getDeclaredField("age");//获取class指定属性 Field desField = class1.getField("des");//获取class指定的public属性 } catch (NoSuchFieldException e) { e.printStackTrace(); } Method[] methods = class1.getDeclaredMethods();//获取class对象的所有声明方法 Method[] allMethods = class1.getMethods();//获取class对象的所有方法 包括父类的方法 Class parentClass = class1.getSuperclass();//获取class对象的父类Class[] interfaceClasses = class1.getInterfaces();//获取class对象的所有接口&/?& Constructor[] allConstructors = class1.getDeclaredConstructors();//获取class对象的所有声明构造函数Constructor[] publicConstructors = class1.getConstructors();//获取class对象public构造函数try {&/?&&/?& Constructor constructor = class1.getDeclaredConstructor(new Class[]{String.class});//获取指定声明构造函数&/?& Constructor publicConstructor = class1.getConstructor(new Class[]{});//获取指定声明的public构造函数 } catch (NoSuchMethodException e) { e.printStackTrace(); } Annotation[] annotations = class1.getAnnotations();//获取class对象的所有注解 Annotation annotation = class1.getAnnotation(Deprecated.class);//获取class对象指定注解 Type genericSuperclass = class1.getGenericSuperclass();//获取class对象的直接超类的 TypeType[] interfaceTypes = class1.getGenericInterfaces();//获取class对象的所有接口的type集合 4.)class对象动态生成 //第一种方式 Class对象调用newInstance()方法生成Object obj = class1.newInstance();//第二种方式 对象获得对应的Constructor对象,再通过该Constructor对象的newInstance()方法生成Constructor constructor =class1.getDeclaredConstructor(new Class[]{String.class});//获取指定声明构造函数&/?& obj = constructor.newInstance(new Object[]{"lcj"}); 5.)动态调用函数 try { // 生成新的对象:用newInstance()方法 Object obj = class1.newInstance(); //判断该对象是否是Person的子类 boolean isInstanceOf = obj instanceof P //首先需要获得与该方法对应的Method对象 Method method = class1.getDeclaredMethod("setAge", new Class[]{int.class}); //调用指定的函数并传递参数 method.invoke(obj, 28); method = class1.getDeclaredMethod("getAge"); Object result = method.invoke(obj, new Class[]{}); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } 6.)通过反射机制获取泛型类型 例如下面这种结构 //People类 public class People {}//Person类继承People类 public class Person extends People implements PersonInterface {}//PersonInterface接口 public interface PersonInterface{} 获取泛型类型 Personperson = new Person&&();//第一种方式 通过对象getClass方法 Class class1 = person.getClass();&/?& Type genericSuperclass = class1.getGenericSuperclass();//获取class对象的直接超类的 Type Type[] interfaceTypes = class1.getGenericInterfaces();//获取class对象的所有接口的Type集合 getComponentType(genericSuperclass); getComponentType(interfaceTypes[0]); getComponentType具体实现 private Class getComponentType(Type type) {&/?& Class componentType =if (type instanceof ParameterizedType) {&/?& //getActualTypeArguments()返回表示此类型实际类型参数的 Type 对象的数组。 Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments(); if (actualTypeArguments != null && actualTypeArguments.length & 0) { componentType = (Class) actualTypeArguments[0];&/?& } } else if (type instanceof GenericArrayType) { // 表示一种元素类型是参数化类型或者类型变量的数组类型 componentType = (Class) ((GenericArrayType) type).getGenericComponentType();&/?& } else { componentType = (Class)&/?& }return componentT } 6.)通过反射机制获取注解信息 这里重点以获取Method的注解信息为例 try { //首先需要获得与该方法对应的Method对象 Method method = class1.getDeclaredMethod("jumpToGoodsDetail", new Class[]{String.class, String.class}); Annotation[] annotations1 = method.getAnnotations();//获取所有的方法注解信息 Annotation annotation1 = method.getAnnotation(RouterUri.class);//获取指定的注解信息 TypeVariable[] typeVariables1 = method.getTypeParameters(); Annotation[][] parameterAnnotationsArray = method.getParameterAnnotations();//拿到所有参数注解信息 Class[] parameterTypes = method.getParameterTypes();//获取所有参数class类型&/?& Type[] genericParameterTypes = method.getGenericParameterTypes();//获取所有参数的type类型 Class returnType = method.getReturnType();//获取方法的返回类型&/?& int modifiers = method.getModifiers();//获取方法的访问权限 } catch (NoSuchMethodException e) { e.printStackTrace(); } 反射机制的应用场景: · 逆向代码 ,例如反编译 · 与注解相结合的框架 例如Retrofit · 单纯的反射机制应用框架 例如EventBus 2.x · 动态生成类框架 例如Gson 反射机制的优缺点: 优点: 运行期类型的判断,动态类加载,动态代理使用反射。 缺点: 性能是一个问题,反射相当于一系列解释操作,通知jvm要做的事情,性能比直接的要慢很多。 总结: Java的反射机制在平时的业务开发过程中很少使用到,但是在一些基础框架的搭建上应用非常广泛,今天简单的总结学习了一下,还有很多未知的知识等以后用到再做补充。文章来源:麦穗技术
免责声明:本站部分内容、图片、文字、视频等来自于互联网,仅供大家学习与交流。相关内容如涉嫌侵犯您的知识产权或其他合法权益,请向本站发送有效通知,我们会及时处理。反馈邮箱&&&&。
学生服务号
在线咨询,奖学金返现,名师点评,等你来互动 序言
在学习java基础时,由于学的不扎实,讲的实用性不强,就觉得没用,很多重要的知识就那样一笔带过了,像这个马上要讲的反射机制一样,当时学的时候就忽略了,到后来学习的知识中,很多东西动不动就用反射,所以回过头来把这个给重新补一下,自己欠下的债,迟早是要还的。
---WH
一、什么是反射?
在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制。通俗点讲,通过反射,该类对我们来说是完全透明的,想要获取任何东西都可以。
想要使用反射机制,就必须要先获取到该类的字节码文件对象(.class),通过字节码文件对象,就能够通过该类中的方法获取到我们想要的所有信息(方法,属性,类名,父类名,实现的所有接口等等),每一个类对应着一个字节码文件也就对应着一个Class类型的对象,也就是字节码文件对象。
获取字节码文件对象的三种方式。
1、Class clazz1 = Class.forName("全限定类名"); //通过Class类中的静态方法forName,直接获取到一个类的字节码文件对象,此时该类还是源文件阶段,并没有变为字节码文件。
2、Class clazz2& = Person. //当类被加载成.class文件时,此时Person类变成了.class,在获取该字节码文件对象,也就是获取自己, 该类处于字节码阶段。
3、Class clazz3 = p.getClass(); //通过类的实例获取该类的字节码文件对象,该类处于创建对象阶段
有了字节码文件对象才能获得类中所有的信息,我们在使用反射获取信息时,也要考虑使用上面哪种方式获取字节码对象合理,视不同情况而定。下面介绍Class类的功能。
二、反射机制能够获取哪些信息?Class类的API详解。
2.1、通过字节码对象创建实例对象
2.2、获取指定构造器方法。constructor 如果没有无参构造,只有有参构造如何创建实例呢?看下面
总结上面创建实例对象:Class类的newInstance()方法是使用该类无参的构造函数创建对象, 如果一个类没有无参的构造函数, 就不能这样创建了,可以调用Class类的 getConstructor(String.class,int.class)方法获取一个指定的构造函数然后再调用Constructor类的newInstance("张三",20)方法创建对象
获取全部构造方法
2.3、获取成员变量并使用 Field对象
获取指定成员变量
&Class.getField(String)方法可以获取类中的指定字段(可见的), 如果是私有的可以用getDeclaedField("name")方法获取,通过set(obj, "李四")方法可以设置指定对象上该字段的值, 如果是私有的需要先调用setAccessible(true)设置访问权限,用获取的指定的字段调用get(obj)可以获取指定对象中该字段的值
获取全部成员变量
2.4、获得方法并使用 Method
Class.getMethod(String, Class...) 和 Class.getDeclaredMethod(String, Class...)方法可以获取类中的指定方法,
如果为私有方法,则需要打开一个权限。setAccessible(true);
用invoke(Object, Object...)可以调用该方法,
跟上面同理,也能一次性获得所有的方法
2.5、获得该类的所有接口
Class[] getInterfaces():确定此对象所表示的类或接口实现的接口
返回值:接口的字节码文件对象的数组
2.6、获取指定资源的输入流
InputStream getResourceAsStream(String name)
return:一个 InputStream 对象;如果找不到带有该名称的资源,则返回 null
参数:所需资源的名称,如果以"/"开始,则绝对资源名为"/"后面的一部分。
2.7、动态代理的概述和实现
动态代理:一种设计模式,其非常简单,很容易理解,你自己可以做这件事,但是觉得自己做非常麻烦或者不方便,所以就叫一个另一个人(代理)来帮你做这个事情,而你就不用管了,这就是动态代理。举个例子,买火车票叫人代买。&
在程序运行过程中产生的这个对象,而程序运行过程中产生对象其实就是我们刚才反射讲解的内容,所以,动态代理其实就是通过反射来生成一个代理
在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。我们有更强大的代理cglib,Proxy类中的方法创建动态代理类对象
分三步,但是注意JDK提供的代理正能针对接口做代理,也就是下面的第二步返回的必须要是一个接口。
1、new出代理对象,通过实现InvacationHandler接口,然后new出代理对象来。
2、通过Proxy类中的静态方法newProxyInstance,来将代理对象假装成那个被代理的对象,也就是如果叫人帮我们代买火车票一样,那个代理就假装成我们自己本人
3、执行方法,代理成功
将代理对象中的内容进行实现
1、2、3步
注意newProxyInstance的三个参数,第一个,类加载器,第二个被代理对象的接口,第三个代理对象。
2.8、还有很多方法,比如获得类加载器,等等
具体还需要别的,就通过查看API文档来解决。
三、反射机制的应用实例
3.1、利用反射,在泛型为int的arryaList集合中存放一个String类型的对象
原理:集合中的泛型只在编译器有效,而到了运行期,泛型则会失效,
3.2、利用反射,简化编写Servlet的个数。
什么意思呢?每当我们写一个功能时,就需要写一个对应的Servlet,导致最后Servlet有很多,自己都看不过来,所以对其进行了优化,两种方式,
3.2.1、每次从页面传过来一个参数,method="xxx"; 然后编写一个Servlet,获得其参数method的值,进行判断,如果是add,则调用add方法,如果是delete,则调用delete方法,这样就可以写在一个servlet中实现所有的功能了。
3.2.2、利用反射
编写一个BaseServlet继承HttpServlet,这是一个通用的BaseServlet。需要明白servlet的生命周期
编写具体实现的方法servlet类。
MySerlvet001 extends BaseServlet
解释:需要明白servlet的生命周期,也就是service方法,因为是servlet,所以在访问的时候,会经过service方法,而子类MyServlet001中并没有,所以就到父类BaseServlet中找,发现有,然后获取参数即知道了需要调用什么方法,因为方法的编写都在子类中,所以通过反射,获取到子类中对应的方法并运行,其中需要注意的是this这个参数在BaseServlet中的用法。需要理解它。才能理解我们这个程序。
反射基本上就这样讲完了,其实就是对其一些api进行讲解,不懂的就查看API,重要的思想,就要在实际中遇到了才能得到更好的理解。先这样过一遍,零零碎碎的知识。
阅读(...) 评论()安全检查中...
请打开浏览器的javascript,然后刷新浏览器
< 浏览器安全检查中...
还剩 5 秒&}