一、概述
反射,指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对任意一个对象,都能调用它的任意一个方法。这种动态获取信息,以及动态调用对象方法的功能,叫做java语言的反射机制。很多框架,比如ORM映射框架Hibernate就大量运用了反射,通过反射可以获取到Entity里配置的表名,字段名,表关系等等,然后生成数据库sql、填充数据等等。
通过反射概括性的可以分为获取属性、获取注解、获取泛型、执行方法、修改属性值等几类。
二、获取属性
给定一个对象,可以获取对象内的属性值,无论是否是私有,都可以获取,示例代码如下:
public static void readAttributeValue(Object obj){String nameVlues="";//得到classClass cls = obj.getClass();//得到所有属性Field[] fields = cls.getDeclaredFields();for (int i=0;i<fields.length;i++){//遍历try {//得到属性Field field = fields[i];//打开私有访问field.setAccessible(true);//获取属性String name = field.getName();//获取属性值Object value = field.get(obj);//一个个赋值nameVlues += field.getName()+":"+value+",";} catch (IllegalAccessException e) {e.printStackTrace();}}}
三、获取注解
写在属性或者类上等其它地方的注解,也可以用反射获取到,示例代码如下:
public static <T> void parseMethod(Class<T> clazz) {try {T obj = clazz.newInstance();for (Method method : clazz.getDeclaredMethods()) {MyMethodAnnotation methodAnnotation = method.getAnnotation(MyMethodAnnotation.class);if (methodAnnotation != null) {// 通过反射调用带有此注解的方法method.invoke(obj, methodAnnotation.uri());}MyClassAndMethodAnnotation myClassAndMethodAnnotation = method.getAnnotation(MyClassAndMethodAnnotation.class);if (myClassAndMethodAnnotation != null) {if (EnumType.util.equals(myClassAndMethodAnnotation.classType())) {System.out.println("this is a util method");} else {System.out.println("this is a other method");}System.out.println(Arrays.toString(myClassAndMethodAnnotation.arr()));// 打印数组System.out.println(myClassAndMethodAnnotation.color());// 输出颜色}System.out.println("\t\t-----------------------");}} catch (Exception e) {e.printStackTrace();}}public static <T> void parseType(Class<T> clazz) {try {MyClassAndMethodAnnotation myClassAndMethodAnnotation = clazz.getAnnotation(MyClassAndMethodAnnotation.class);if (myClassAndMethodAnnotation != null) {if (EnumType.util.equals(myClassAndMethodAnnotation.classType())) {System.out.println("this is a util class");} else {System.out.println("this is a other class");}}MyClassAnnotation myClassAnnotation = clazz.getAnnotation(MyClassAnnotation.class);if (myClassAnnotation != null) {System.err.println(" class info: " + myClassAnnotation.uri());}} catch (Exception e) {e.printStackTrace();}}public static void main(String[] args) {parseMethod(TestAnnotation.class);parseType(TestAnnotation.class);}
四、获取泛型
如果属性或者类有用到泛型,也可以通过反射或者到泛型,示例代码如下:
public static void getType() throws Exception {Class<GenericTest> clazz = GenericTest.class;Field f = clazz.getDeclaredField("score");// 直接使用getType()取出的类型只对普通类型的成员变量有效Class<?> a = f.getType();// 下面将看到仅输出java.util.MapSystem.out.println("score的类型是:" + a);// 获得成员变量f的泛型类型Type gType = f.getGenericType();// 如果gType类型是ParameterizedType对象if(gType instanceof ParameterizedType){// 强制类型转换ParameterizedType pType = (ParameterizedType)gType;// 获取原始类型Type rType = pType.getRawType();System.out.println("原始类型是:" + rType);// 取得泛型类型的泛型参数Type[] tArgs = pType.getActualTypeArguments();System.out.println("泛型信息是:");for (int i = 0; i < tArgs.length; i++){System.out.println("第" + i + "个泛型类型是:" + tArgs[i]);}}else{System.out.println("获取泛型类型出错!");}}
五、执行方法
对象内的方法,也可以进行调用,示例代码如下:
public static void invokeMethod() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {Foo foo = new Foo("这个一个Foo对象!");Class clazz = foo.getClass();Method m1 = clazz.getDeclaredMethod("outInfo");Method m2 = clazz.getDeclaredMethod("setMsg", String.class);Method m3 = clazz.getDeclaredMethod("getMsg");m1.invoke(foo);m2.invoke(foo, "重新设置msg信息!");String msg = (String) m3.invoke(foo);System.out.println(msg);}
六、修改属性
如果对象没有类似setter、getter的方法,也可以直接修改属性值,示例代码如下:
public static void setField(){Class<Test> aClass = =Test.class;Field field = null;try {field = aClass.getDeclaredField("a");//将私有属性开发可修改field.setAccessible(true);field.set(this, 1000.0);Object o = field.get(this);System.err.println(o);} catch (NoSuchFieldException | IllegalAccessException e) {e.printStackTrace();}}
有兴趣的大佬大神可以关注下小弟的微信公共号,一起学习交流,扫描以下二维码关注即可。
文章转载自尚浩宇,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。





