今天看看Java反射
2016-07-21 16:38
525 查看
什么是Java反射
Java反射机制是在运行状态中,对于任何一个类,都能知道这个类的属性和方法, 对于任何一个对象,都能够调用它的任意一个方法和属性。Java反射主要是用来
在运行时判断任意一个对象所属的类。
在运行时构造任意一个类的对象。
在运行时判断任意一个类所具有的成员变量和方法。
在运行时调用任意一个对象的方法,生成动态代理。
反射的三种方式
通过 Class.forName() 方法加载字符串,就可以得到该字符串做代表的Class对象Class<?> cls = Class.forName("com.java.Demo");
通过类名调用class属性得到该类的Class对象。
Class<?> cls = Demo.class;
通过实例的 getClass() 方法得到Class对象
Demo demo = new Demo(); Class <?> cls = demo.getClass();
这三种方法,最后都是要得到一个Class对象,然后获取字段和函数的的方法,都是围绕着这个Class对象来实现的。
生成对象
先获得Class对象,然后通过该Class对象的newInstance()方法获取对象。Class<?> classType = String.class; Object obj = classType.newInstance();
先获得Class对象,然后通过该对象获得对应的Constructor对象,再通过该Constructor对象的newInstance()方法生成
Class<?> classType = Customer.class; // 获得Constructor对象,此处获取第一个无参数的构造方法的 Constructor cons = classType.getConstructor(new Class[] {}); // 通过构造方法来生成一个对象 Object obj = cons.newInstance(new Object[] {});
但是,上面这种情况只适用于默认的 无参构造函数 ,但是如果是有参构造函数,则会报错。
Exception in thread "main" java.lang.InstantiationException: com.gzl.demo.InvokeTest at java.lang.Class.newInstance(Class.java:418) at com.gzl.demo.InvokeTest.main(InvokeTest.java:33) Caused by: java.lang.NoSuchMethodException: com.gzl.demo.InvokeTest.<init>() at java.lang.Class.getConstructor0(Class.java:2971) at java.lang.Class.newInstance(Class.java:403) ... 1 more
这个时候,可以用下面的方法:
Class<?> classType = InvokeTest.class; //getConstructor(Class<?>... parameterTypes),传递的是可变Class参数 Constructor cons2 = classType.getConstructor(new Class[] {String.class, int.class}); //当是基本数据类型传入的时候,需要一个包装类来包装它,但是jdk1.5也可以直接传入基本数据类型了,因为编译器会帮你自动装箱,拆箱 Object obj2 = cons2.newInstance(new Object[] {"ZhangSan",20});
两种不同的方法的区别
通过反射创建新的类示例,有两种方式:Class.newInstance()
Constructor.newInstance()
以下对两种调用方式给以比较说明:
Class.newInstance() 只能够调用无参的构造函数,即默认的构造函数;
Constructor.newInstance() 可以根据传入的参数,调用任意构造构造函数。
Class.newInstance() 抛出所有由被调用构造函数抛出的异常。
Class.newInstance() 要求被调用的构造函数是可见的,也即必须是public类型的;
Constructor.newInstance() 在特定的情况下,可以调用私有的构造函数。
获取函数Method
一行代码获取所有的方法。Method[] methods = clazz.getDeclaredMethods();
可以看看Method的API
大概就是几个Get方法,常用的包括:
getModifiers()
以整数形式返回此 Method 对象所表示方法的 Java 语言修饰符。
getName()
以 String 形式返回此 Method 对象表示的方法名称。
getReturnType()
返回一个 Class 对象,该对象描述了此 Method 对象所表示的方法的正式返回类型。
invoke(Object obj, Object… args)
对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
在使用invoke方法之前可以先用
class.getMethod(String name,Class
getxxx(field,method,constructor)和getDeclaredxxx(field,method,constructor)的区别
getxxx() 只能访问类中的私有字段,而共有的字段是无法访问的,能访问从其他类继承下来的公共方法。返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。返回数组中的元素没有排序,也没有任何特定的顺序。
如果类或接口没有可访问的公共字段,或者表示一个数组类、一个基本类型或 void,则此方法返回长度为 0 的数组。
特别地,如果该 Class对象表示一个类,则此方法返回该类及其所有超类的公共字段。
如果该 Class 对象表示一个接口,则此方法返回该接口及其所有超接口的公共字段。
该方法不反映数组类的隐式长度字段。用户代码应使用 Array 类的方法来操作数组。
getDeclaredxxx()
返回一个构造函数对象数组,反映由这个类对象所表示的类所声明的所有构造函数。
这些都是public、protected、default和private。返回的数组中的元素没有排序。
如果类有一个默认的构造函数,它被包含在返回的数组中。如果这个类对象表示一个接口,一个原始类型,一个数组类,或void,此方法返回一个长度为0的数组。
一个例子获取所有需要的方法
记得新建一个类,然后改一下forName()里面包的路径。package com.gzl.demo; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; public class Test { public static void main(String[] args){ try { //获取Student的Class对象 Class<?> clazz = Class.forName("com.gzl.demo.Student"); //获取该类中所有的属性 Field[] fields = clazz.getDeclaredFields(); System.out.println("下面打印类中所有属性"); //遍历所有的属性 for (Field field : fields) { field.setAccessible(true); //打印属性信息,包括访问控制修饰符,类型及属性名 System.out.println(" 修饰符:" + Modifier.toString(field.getModifiers())); System.out.println(" 类型:" + field.getType().toString()); System.out.println(" 属性名:" + field.getName()); System.out.println(); } //获取该类中的所有方法 Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { System.out.println(" 修饰符:" + Modifier.toString(method.getModifiers())); System.out.println(" 方法名:" + method.getName()); System.out.println(" 返回类型:" + method.getReturnType()); //获取方法的参数对象 Class<?>[] clazzes = method.getParameterTypes(); for (Class<?> class1 : clazzes) { System.out.println(" 参数类型:" + class1); System.out.println(); } } } catch (Exception e) { e.printStackTrace(); } } }
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- Python动态类型的学习---引用的理解
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序