java学习笔记之反射
2015-10-01 17:34
711 查看
1、获得Class对象(反射的源头)
三种方式: a、类.class b、对象.getClass() C、Class.forName(String className) (className为完整类名,包括包名)
2、获取类名、构造函数、属性、方法
a、获取类名: getName() 获取完整类名,包含包名 getSimpleName() 获取类名,不包含包名 b、获取构造函数 Constructor getConstuctors() 获取public权限构造函数,无法获取其它权限构造函数 getDeclaredConstructors() 获取所有权限构造函数 getConstructor(Class... parameterTypes) 获取指定public权限构造函数 getDeclaredConstructor(Class... parameterTypes) 获取指定任意权限构造函数 c、获取属性 Field getFields() 获取public权限属性,无法获取其它权限构造属性 getDeclaredFields() 获取所有权限属性 getField(String name) 获取指定public权限属性 getDeclaredField(String name) 获取指定任意权限属性 d、获取方法 Method getMethods() 获取public权限方法,无法获取其它权限方法 getDeclaredMethods() 获取所有权限方法 getMethod(Class... parameterTypes) 获取指定public权限方法 getDeclaredMethod(Class... parameterTypes) 获取指定任意权限方法
代码示例:
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * 通过反射,获取类名、构造函数、属性、方法 * @author ly1 * */ public class GetInfo{ public static void main(String[] args) throws Exception { //获取Class对象===================================================================================== Student student = new Student(); Class clazz = Student.class; clazz = student.getClass(); clazz = Class.forName("Reflect.Student"); //获取类名=========================================================================================== String name = clazz.getName(); //完整类名,包括包名 System.out.println("获取类名:"+name); name = clazz.getSimpleName(); //类名,不含包名 System.out.println("获取完整类名:"+name); //获取构造函数======================================================================================= //获取public权限构造函数,无法获取其它权限构造函数 Constructor[] constructors = clazz.getConstructors(); System.out.println("获取public权限构造函数,无法获取其它权限构造函数:"); System.out.println("\t"+constructors.length); for (Constructor constructor : constructors) { System.out.println("\t"+constructor); } //获取所有权限构造函数,包括public、default、protected、private constructors = clazz.getDeclaredConstructors(); System.out.println("获取所有权限构造函数,包括public、default、protected、private:"); System.out.println("\t"+constructors.length); for (Constructor constructor : constructors) { System.out.println("\t"+constructor); } //根据构造函数的参数类型获取指定构造函数 Constructor constructor = clazz.getConstructor(String.class,char.class,int.class,double.class); System.out.println("根据构造函数的参数类型获取指定构造函数:"); System.out.println("\t"+constructor); //获取属性========================================================================================== //获取public权限属性,无法获取其它权限属性 Field[] fields = clazz.getFields(); System.out.println("获取public权限属性,无法获取其它权限属性 :"); System.out.println("\t"+fields.length); for(Field f : fields){ System.out.println("\t"+f); } //获取所有权限的属性,包括public、default、protected、private fields = clazz.getDeclaredFields(); System.out.println("获取所有权限的属性,包括public、default、protected、private :"); System.out.println("\t"+fields.length); for(Field f : fields){ System.out.println("\t"+f); } //根据属性名获取指定属性 Field field = clazz.getDeclaredField("name"); System.out.println("根据属性名获取指定属性:"); System.out.println("\t"+field); //获取方法=========================================================================================== //获取public权限方法,无法获取其它权限方法,包括直接或间接父类public方法 Method[] methods = clazz.getMethods(); System.out.println("获取public权限方法,无法获取其它权限方法,包括直接或间接父类public方法:"); System.out.println("\t"+methods.length); for (Method method : methods) { System.out.println("\t"+method); } //获取所有权限的方法,包括public、default、protected、private methods = clazz.getDeclaredMethods(); System.out.println("获取所有权限的方法,包括public、default、protected、private:"); System.out.println("\t"+methods.length); for (Method method : methods) { System.out.println("\t"+method); } //根据方法名和参数类型,获取指定方法 Method method = clazz.getDeclaredMethod("setName", String.class); System.out.println("根据方法名和参数类型,获取指定方法:"); System.out.println("\t"+method); } } 结果: 获取类名:Reflect.Student 获取完整类名:Student 获取public权限构造函数,无法获取其它权限构造函数: 2 public Reflect.Student() public Reflect.Student(java.lang.String,char,int,double) 获取所有权限构造函数,包括public、default、protected、private: 2 public Reflect.Student() public Reflect.Student(java.lang.String,char,int,double) 根据构造函数的参数类型获取指定构造函数: public Reflect.Student(java.lang.String,char,int,double) 获取public权限属性,无法获取其它权限属性 : 1 public double Reflect.Student.height 获取所有权限的属性,包括public、default、protected、private : 4 private java.lang.String Reflect.Student.name char Reflect.Student.sex protected int Reflect.Student.age public double Reflect.Student.height 根据属性名获取指定属性: private java.lang.String Reflect.Student.name 获取public权限方法,无法获取其它权限方法,包括直接或间接父类public方法: 15 public java.lang.String Reflect.Student.getName() public void Reflect.Student.setName(java.lang.String) public int Reflect.Student.getAge() public char Reflect.Student.getSex() public void Reflect.Student.setHeight(double) public double Reflect.Student.getHeight() public boolean java.lang.Object.equals(java.lang.Object) public final native java.lang.Class java.lang.Object.getClass() public final void java.lang.Object.wait() throws java.lang.InterruptedException public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException public native int java.lang.Object.hashCode() public java.lang.String java.lang.Object.toString() public final native void java.lang.Object.notifyAll() public final native void java.lang.Object.notify() 获取所有权限的方法,包括public、default、protected、private: 8 public java.lang.String Reflect.Student.getName() public void Reflect.Student.setName(java.lang.String) public int Reflect.Student.getAge() public char Reflect.Student.getSex() public void Reflect.Student.setHeight(double) protected void Reflect.Student.setAge(int) private void Reflect.Student.setSex(char) public double Reflect.Student.getHeight() 根据方法名和参数类型,获取指定方法: public void Reflect.Student.setName(java.lang.String)
3、动态操作构造函数、属性、方法
1)操作构造函数 a、利用Class对象调用空构造: Class对象.newInstance() 该方法得确保该类有空构造(显示或隐式) b、利用Constructor.newInstance(): Constructor对象.newInstance() 该方法可以调用任意构造方法,如果不可访问,须设置setAccessible(true) 2)操作属性 a、操作可访问属性 Field对象.set(Object obj,Object value) b、操作不可访问属性 须先设置 Field对象setAccessible(true) 然后 Field对象.set(Object obj,Object value) 3)操作方法 a、操作可访问方法 Method对象.invoke(Object obj,Object... args) b、操作不可访问方法 须先设置 Method对象setAccessible(true) 然后 Method对象.invoke(Object obj,Object... args)
代码示例:
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * 通过反射操作类的构造函数、属性、方法 * @author ly1 * */ public class OperateInfo { public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException, NoSuchFieldException { //获取Class对象 Class clazz = Student.class; //利用反射API创建对象==================================================================== //直接调用Class对象的newInstance()方法,必须保证Student对象有空构造(显示或隐式) Student student = (Student) clazz.newInstance(); System.out.println(student); //获取到构造函数创建对象 Constructor<Student> constructor = clazz.getConstructor(String.class,char.class,int.class,double.class); student = constructor.newInstance("张三",'男',20,178.51); System.out.println(student); //利用反射API操作属性 //操作可访问属性 Field field = clazz.getField("height"); field.set(student, 188.00); System.out.println(field.get(student)); //操作不可访问属性,设置setAccessible(true) field = clazz.getDeclaredField("name"); field.setAccessible(true); //使反射对象该属性在使用时不对其进行安全检查 field.set(student, "李四"); System.out.println(field.get(student)); //利用反射API操作方法 //操作可访问方法 Method method = clazz.getMethod("setName", String.class); method.invoke(student, "王麻子"); System.out.println(student.getName()); //操作不可访问方法,设置setAccessible(true) method = clazz.getDeclaredMethod("setSex", char.class); method.setAccessible(true); //使反射对象该方法在使用时不对其进行安全检查 method.invoke(student, '女'); System.out.println(student.getSex()); } } 结果:Reflect.Student@39e2ee3f Reflect.Student@24348ab2 188.0 李四 王麻子 女
4、反射机制性能
使用反射机制性能降低,如果禁止安全检查,性能会有所上升,但还是比不使用反射性能低。
代码测试:
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * 测试反射机制的性能 * @author ly1 * */ public class ReflectPerformance { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { Class clazz = Class.forName("Reflect.Student"); Student stu = (Student) clazz.newInstance(); test01(stu); test02(clazz,stu); test03(clazz,stu); } public static void test01(Student stu){ long startTime = System.currentTimeMillis(); for(int i = 0;i < 1000000000L;i++){ stu.getName(); } long endTime = System.currentTimeMillis(); System.out.println("不使用反射机制运行时间为:"+(endTime - startTime) +"ms"); } public static void test02(Class clazz,Student stu){ try { Method method = clazz.getMethod("getName"); long startTime = System.currentTimeMillis(); for(int i = 0;i < 1000000000L;i++){ method.invoke(stu, null); } long endTime = System.currentTimeMillis(); System.out.println("使用反射机制,进行安全检查运行时间为:"+(endTime - startTime) +"ms"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void test03(Class clazz, Student stu){ try { Method method = clazz.getMethod("getName"); method.setAccessible(true); long startTime = System.currentTimeMillis(); for(int i = 0;i < 1000000000L;i++){ method.invoke(stu, null); } long endTime = System.currentTimeMillis(); System.out.println("使用反射机制,不进行安全检查运行时间为:"+(endTime - startTime) +"ms"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 结果:不使用反射机制运行时间为:332ms 使用反射机制,进行安全检查运行时间为:1769ms 使用反射机制,不进行安全检查运行时间为:1201ms
5、反射操作泛型
1)获取泛型参数 Method对象.getGenericParameterTypes():Type[] 获取具体类型: ParameterizedType对象.getActualTypeArguments():Type[] 2)获取泛型返回值 Method对象.getGenericReturnType():Type 获取具体类型: ParameterizedType对象.getActualTypeArguments():Type[]
代码示例:
import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.Map; /** * 反射操作泛型 * @author ly1 * */ public class ReflectGeneric { public static List<Integer> test(Map<String,Student> map,List<Double> list){ return null; } public static void main(String[] args) { try{ Class clazz = ReflectGeneric.class; Method method = clazz.getMethod("test", Map.class,List.class); //获取泛型参数的类型 Type[] types = method.getGenericParameterTypes(); for (Type type : types) { System.out.println("泛型参数:"+type); if(type instanceof ParameterizedType){ Type[] aTypes = ((ParameterizedType)type).getActualTypeArguments(); for (Type type2 : aTypes) { System.out.println("\t"+type2); } } } //获取泛型返回值的类型 Type type = method.getGenericReturnType(); System.out.println("泛型返回值:"+type); if(type instanceof ParameterizedType){ Type[] aTypes = ((ParameterizedType)type).getActualTypeArguments(); for (Type type2 : aTypes) { System.out.println("\t"+type2); } } } catch(Exception e){ } } } 结果: 泛型参数:java.util.Map<java.lang.String, Reflect.Student> class java.lang.String class Reflect.Student 泛型参数:java.util.List<java.lang.Double> class java.lang.Double 泛型返回值:java.util.List<java.lang.Integer> class java.lang.Integer
相关文章推荐
- 关于项目刚才还能运行的,重启Myeclipse就不能运行(报错)的解决方法
- JAVA基础--db10_java多态-内部类
- JAVA SE 多态的实现机制
- Java线程生命模型
- Eclipse 常用快捷键
- javaweb多窗口展示网页
- JPA && Spring Data && Spring Data JPA
- 工厂模式---java代码实现
- Java小技巧
- java中抽象类与接口的不同之处
- Java多线程1:进程与线程概述
- Java 定时器
- 配置Xampp+Netbeans的PHP可调试开发环境
- SpringMVC 学习指南<一>
- java 实现文件复制的两种方式
- Struts 的数据校验和验证框架
- Java中的异常处理机制的简单原理和应用
- Java模拟简易ATM机运行(无界面、无数据库)
- Maven安装与使用入门
- LintCode-O(1)检测2的幂次