我们应用会用到反射这个知识点,肯定是想要在运行时得到类的信息,根据类的那些信息去做一些特定的操作。那么,首先无疑就是得到类的信息,在JDK中提供了Class对象来保存类的信息。所以,反射的第一步就是得到Class对象。在JDK中提供了两种方式得到Class对象。第一种,如果编写代码的时候,就知道Class的名字,可以直接用如下方式得到Class对象:

    //第一种,如果编写代码的时候,就知道Class的名字,可以直接用如下方式得到Class对象:Class exampleObjectClass = ExampleObject.class;//第二种,如果在编写代码的时候,不知道类的名字,但是在运行时的时候,可以得到一个类名的字符串,可以用如下的方式获取Class对象://注意,此方法需要有2个条件,第一,forName中的字符串必须是全限定名,第二,//这个Class类必须在classpath的路径下面,因为该方法会抛出ClassNotFoundException的异常。Class exampleObjectClass2 = Class.forName("com.team.frame.fanshe.ExampleObject");

下面介绍通过反射可以获取那些信息:

1. 得到类的名字

   /*** 得到类的名字* 类的名字有两种方式得到,一种是getName(),一种是getSimpleName()。* 第一种得到的是全限定名,第二种得到的是这个类的名字,不带包名。看下面的例子:Class对象,已经通过上面的代码得到了。*/String fullClassName = exampleObjectClass.getName();String simpleClassName = exampleObjectClass.getSimpleName();System.out.println(fullClassName);System.out.println(simpleClassName);

2. 得到类的包名、父类和实现的接口

    //得到包信息Package aPackage = exampleObjectClass.getPackage();System.out.println(aPackage);//得到父类Class superClass = exampleObjectClass.getSuperclass();System.out.println(superClass.getSimpleName());//判断父类是否是抽象类boolean abstract1 = Modifier.isAbstract(superClass.getModifiers());//我们还可以得到父类实现的接口Class[] interfaces = superClass.getInterfaces();System.out.println("父类的接口" + interfaces[0]);

3. 利用Java反射可以得到一个类的构造器,并根据构造器,在运行时动态的创建一个对象

    Constructor[] constructors = exampleObjectClass.getConstructors();for(Constructor cos:constructors){System.out.println(cos.toString());}//如果,事先知道要访问的构造方法的参数类型,可以利用如下方法获取指定的构造方法,例子如下:Constructor constructor = exampleObjectClass.getConstructor(String.class);System.out.println(constructor);//此外,如果我们不知道构造器的参数,只能得到所有的构造器对象,那么可以用如下方式得到每一个构造器对想的参数:Constructor[] constructors2 = exampleObjectClass.getConstructors();for(Constructor cos2:constructors2){Class[] parameterTypes = cos2.getParameterTypes();for(Class cla:parameterTypes){System.out.println("参数类型"+cla.toString());}}//根据构造器创建一个对象//这个创建对象的方式有2个条件,第一是通过有参构造器创建的,第二,构造器对象必须通过传入参数信息的getConstructor得到。//第一个条件,对于无参构造方法就可以创建的对象,不需要得到构造器对象,直接Class对象调用newInstance()方法就直接创建对象。//第二个条件,构造器对象必须通过exampleObjectClass.getConstructor(String.class);这种形式得到。如果通过getConstructors得到构造器数组//,然后调用指定的构造器对象去创建对象在JDK1.8是会错的。但是JDK1.6是正常的Constructor constructor2 = exampleObjectClass.getConstructor(int.class,Integer.class);Object newInstance = constructor2.newInstance(1,100);System.out.println(newInstance.toString());

4. 利用Java反射可以在运行时得到一个类的变量信息

    /*** 变量* 利用Java反射可以在运行时得到一个类的变量信息,并且可以根据上面讲的方式,创建一个对象,设置他的变量值。首先,通过如下方法,得到所有public的变量:*/Field[] fields = exampleObjectClass.getFields();for(Field fi:fields){System.out.println("变量为"+fi.toString());}//和构造器一样的得到方式一样,我们可以指定一个参数名,然后得到指定的变量:Field field = exampleObjectClass.getField("age");System.out.println(field.toString());//更改变量的值Constructor constructor1 = exampleObjectClass.getConstructor(String.class);ExampleObject newInstance2 = (ExampleObject)constructor1.newInstance("heihei");System.out.println("原来的age"+newInstance2.getAge());field.set(newInstance2, 10);System.out.println("修改后age"+newInstance2.getAge());

5. Java反射给我们除了给我们提供类的变量信息之外,当然也给我们提供了方法的信息

    /*** 方法* Java反射给我们除了给我们提供类的变量信息之外,当然也给我们提供了方法的信息,* 反射可以让我们得到方法名,方法的参数,方法的返回类型,以及调用方法等功能。*/Method[] methods = exampleObjectClass.getMethods();for(Method me:methods){System.out.println("method="+me.getName());}//根据参数获得具体方法Method method = exampleObjectClass.getMethod("setAge", int.class);System.out.println(method.getName());//获取方法的参数类型Class<?>[] parameterTypes = method.getParameterTypes();for(Class clz:parameterTypes){System.out.println("参数名"+clz.getName());System.out.println("类型"+clz.getTypeParameters());}//获得方法返回类型的Class<?> returnType = method.getReturnType();//此外,Java反射支持通过invoke调用得到的方法。例子如下://nvoke第一个参数是这个对象,第二个参数是变长数组,传入该方法的参数。和Field对象同样,对于静态方法同样,可以传入null,调用静态方法。method.invoke(exampleObjectClass.newInstance(), 1);

6. Java给我们提供了在运行时获取类的注解信息,可以得到类注解,方法注解,参数注解,变量注解

    /*** 注解* Java给我们提供了在运行时获取类的注解信息,可以得到类注解,方法注解,参数注解,变量注解。* 与上面获取方式一样,Java提供了2种获取方式,一种是获取全部的注解,返回一个数组,第二种是指定得到指定的注解。* 我们以一个类注解为例,讲解以下这两种获取方式。*///获取类上的注解Class clz = AnnotationObject.class;Annotation[] annotations = clz.getAnnotations();Annotation annotation = clz.getAnnotation(AnnotationObject.class);//根据注解进行后续处理for(Annotation ano:annotations){if(ano instanceof MyAnnotationFanshe){MyAnnotationFanshe annoFanshe=(MyAnnotationFanshe)ano;System.out.println(annoFanshe.name());System.out.println(annoFanshe.value());}}//获取参数上的注解Method method2 = clz.getMethod("doOtherThing",String.class);Class[] params = method2.getParameterTypes();Annotation[][] annotationInParam = method2.getParameterAnnotations();int i = 0;for (Annotation[] annos: annotationInParam){Class para = params[i++];for (Annotation anno : annotations){if(annotation instanceof MyAnnotationFanshe){MyAnnotationFanshe myAnnotation = (MyAnnotationFanshe) annotation;System.out.println("param: " + para.getName());System.out.println("name : " + myAnnotation.name());System.out.println("value :" + myAnnotation.value());}}}

7. 获取泛型

    /*** 泛型* 因为Java泛型是通过擦除来实现的,很难直接得到泛型具体的参数化类型的信息,* 但是我们可以通过一种间接的形式利用反射得到泛型信息。比如下面这个类:* 如果一个方法返回一个泛型类,我们可以通过method对象去调用getGenericReturnType来得到这个泛型类具体的参数化类型是什么。*/Class generObject = GenericObject.class;//反射得到返回类型为泛型类的方法Method method3 = generObject.getMethod("getLists");//调用getGenericReturnType得到方法返回类型中的参数化类型Type genericType = method3.getGenericReturnType();//判断该type对象能不能向下转型为ParameterizedTypeif(genericType instanceof ParameterizedType){//转型成功,调用getActualTypeArguments得到参数化类型的数组,因为有的泛型类,不只只有一个参数化类型如Map<K,V>ParameterizedType parameterizedType = ((ParameterizedType) genericType);//取出数组中的每一个的值,转型为Class对象输出Type[] types = parameterizedType.getActualTypeArguments();for (Type type : types){Class actualClz = ((Class) type);System.out.println("参数化类型为 : " + actualClz);}}//因为方法的参数为泛型类型的可能不止一个,所以通过getGenericParameterTypes得到是一个数组,//我们需要确定每一个元素,是否是具有参数化类型。后续的步骤与上面类似,就不多说了。//如果连方法参数都不带泛型类,那么只剩下最后一种情况,通过变量类型,即用Field类。例子如下:Field field1 = generObject.getField("lists");Type type = field1.getGenericType();if (type instanceof ParameterizedType){ParameterizedType parameterizedType = ((ParameterizedType) type);Type [] types = parameterizedType.getActualTypeArguments();for (Type type1 : types) {System.out.println("参数化类型 : " + ((Class) type1).getTypeName());}}

8. Java反射可以对数组进行操作

    /*** 数组* Java反射可以对数组进行操作,包括创建一个数组,访问数组中的值,以及得到一个数组的Class对象。* 下面,先说简单的,创建数组以及访问数组中的值:在反射中使用Array这个类,是reflect包下面的。*///创建一个int类型的数组,长度为3int[] intArray = (int[])Array.newInstance(int.class, 3);//通过反射形式给数组赋值for(int a=0;a<intArray.length;a++){Array.set(intArray, a, a+2);}//通过反射形式获取数组中的值for(int b=0;b<intArray.length;b++){Array.get(intArray, b);}//上述就是创建数组,访问数组中的值利用反射方式//对于得到一个数组的Class对象,简单的可以用int[].class,或者利用Class.forName的形式得到,写法比较奇怪Class clz2 = Class.forName("[I");System.out.println(clz2.getTypeName());//这个forName中的字符串,[表示是数组,I表示是int,float就是F,double就是D等等,如果要得到一个普通对象的数组Class stringClz = Class.forName("[Ljava.lang.String;");//[表示是数组,L的右边是类名,类型的右边是一个;;//这种方式获取数组的Class对象实在是太繁琐了。//在得到数组的Class对象之后,就可以调用他的一些独特的方法,比如调用getComponentType来得到数组成员的类型信息,如int数组就//是成员类型就是int。System.out.println(clz2.getComponentType().getTypeName());

java 反射调用方法_java的反射机制,以及通过反射获取方法,变量等操作相关推荐

  1. java 操作属性值_java反射机制根据属性名获取属性值的操作

    一.考虑安全访问范围内的属性,没有权限访问到的属性不读取 /** * 根据属性名获取属性值 * * @param fieldName * @param object * @return */ priv ...

  2. java通过属性名获取属性值_java反射机制根据属性名获取属性值的操作

    java反射机制根据属性名获取属性值的操作,属性,对象,反射,访问权限,还可以 java反射机制根据属性名获取属性值的操作 易采站长站,站长之家为您整理了java反射机制根据属性名获取属性值的操作的相 ...

  3. java 强制垃圾回收_Java垃圾回收机制

    Java垃圾回收机制 垃圾回收机制用到finalize.当程序创建对象.数组等引用类型实体时,系统都会在堆内存中为之分配一块内存区,对象就保存在这块内存中,当这块内存不再被任何引用变量引用时,这块内存 ...

  4. java 判断object类型_Java 类继承机制

    封装.继承.多态是面向对象的三大特征,"继承"最主要的目的是为了实现代码的可复用性.通过父类与子类的继承关系,子类继承了父类的成员函数和成员变量,提高了代码的重复利用率.同时,子类 ...

  5. java 镶嵌创建线程_Java多线程——之一创建线程的四种方法

    1.实现Runnable接口,重载run(),无返回值 package thread; public class ThreadRunnable implements Runnable { public ...

  6. java 关键字是运算符_Java的super关键字与instanceof运算符使用方法

    Java super关键字 super 关键字与 this 类似,this 用来表示当前类的实例,super 用来表示父类. super 可以用在子类中,通过点号(.)来获取父类的成员变量和方法.su ...

  7. java 如何调用存储过程_java调用存储过程

    这里是java调用存储过程.package com.lijianbo.procedure; import java.sql.CallableStatement; import java.sql.Con ...

  8. java 异步调用接口_Java接口异步调用

    java接口调用从调用方式上可以分为3类:同步调用,异步调用,回调:同步调用基本不用说了,它是一种阻塞式的调用,就是A方法中直接调用方法B,从上往下依次执行.今天来说说异步调用. 什么是异步调用? 我 ...

  9. java访问类的方法_Java:如何从另一个类访问方法

    小编典典 你需要以某种方式为Alpha类提供对cBeta的引用.有三种方法可以做到这一点. 1)在构造函数中为Alphas提供Beta.在Alpha课堂上写道: public class Alpha ...

  10. java类作用域标识符_java入门 (二) 标识符、数据类型、类型转换、变量、常量、作用域...

    java入门(二) 标识符 数据类型 类型转换 变量.常量.作用域 本次笔记引用B站:狂神说,虽然早就会了,现在回头来敲下基础,加深印象 1.标识符: java所有的组成部分都需要名字.类名丶变量名丶 ...

最新文章

  1. 从hello world 说程序运行机制
  2. zTree实现节点修改的实时刷新
  3. 比特币、莱特币来一发?
  4. webstorm中nodejs代码提示
  5. 华为nova7保密柜_华为发布nova8系列新品 轻松拍出Vlog黄金脸占比
  6. 分词之后的如何做特征选择_特征选择怎么做?这篇文章告诉你
  7. python一元加号_Python一元方程解算系统(需要Sympy库支持)
  8. 问题与事务跟踪系统jira中的版本管理
  9. Python使用BoundedSemaphore对象进行线程同步
  10. 使用PING判断TCP/IP故障
  11. Python 之 字典(dict)的创建、字典生成式、复制添加更新删除、查询遍历比较等
  12. C#网易云音乐中需付费歌曲的下载助手。
  13. GB/T 28448-2019 《信息安全技术 网络安全等级保护测评要求》之安全通信网络测评解读
  14. 前端学习——Js(JavaScript)入门
  15. 基于HMM的拼音输入法
  16. 腾讯程序员平均月薪7.48万,分分钟变身“柠檬精”
  17. H5外部浏览器唤起微信分享
  18. Notepad++下载安装教程
  19. eclipse中的图片路径 image
  20. linux find 隐藏,使用find命令查找Linux中的隐藏文件的方法

热门文章

  1. Oracle RAC更改VIP IP地址_2节点的实验
  2. 如何在 Web 发布规则中使用证书进行 SSL 身份验证
  3. 技术开发(委托)合同怎么写?
  4. javascript === 和==的区别
  5. js导出的xlsx无法打开_js文件操作之——导出Excel (js-xlsx)
  6. java 接口与包_java常用类包接口
  7. html侧滑菜单mui,mui侧滑菜单点击含有mui-action-menu类的控件无法实现侧滑
  8. linux sudo命令全称,linux sudo命令的概念与使用
  9. rhcs集群套件—红帽6的高可用
  10. 酷冷至尊官方psu计算工具_酷冷至尊为Raspberry Pi推出Pi Case 40机壳,提供被动散热、卖27美元起...