Java的反射机制
Java 反射机制
1.Java反射机制是什么?
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
2.Java反射机制的作用:
(1)获得动态加载类的修饰符,包名,类名,使用的接口,继承的父类
(2)动态获取类的所有属性名,修饰符,属性类型
(3)动态获取所有定义的构造器,构造器使用的参数数量和参数类型
(4)动态获取所有方法,方法的返回值类型,方法名,方法参数数量,方法参数类型
(5)动态调用加载类的方法
3.Java中Class类的获取:
Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识。这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。然而,class类就是Java反射的根源。
Class类的获取:
1.通过每个类的隐含的静态成员变量获取
2.通过对象的getClass()方法获取
3.通过Class.forName("全名")方式获取
// 第一种方式:通过每个类的隐含的静态成员变量获取 Class<? extends Student> class1 = Student.class; // 第二种方式:通过对象的getClass()方法获取<br> Student stu = new Student(1, "s"); Class<? extends Student> class2 = stu.getClass(); // 第三种方式:通过Class.forName("全名")方式获取 Class<? extends Student> class3 = null; try { class3 = (Class<? extends Student>) class3.forName("com.usc.lilin.demo.Student"); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("calss1:" + class1); System.out.println("calss2:" + class2); System.out.println("calss3:" + class3); System.out.println("calss1==class3?:" + (class1 == class3)); System.out.println("calss2==class1?:" + (class1 == class2)); System.out.println("calss2==class3?:" + (class3 == class2));
为什么会发生这样子呢?
class1、class2、class3 都是Student的类类型。在Java中,一个类只可能是Class的一个实例对象,所以三者均相等
4.Java类的动态加载:
通过.newInstance()方法创建对象
Student student = class1.newInstance();
5.class的常用API
/** * 获取对象的类的方法的信息 * * @param obij */ public static void getClassMethMSG(Object obj) { Class<? extends Object> class1 = obj.getClass(); // 获取对象的全名 String name = class1.getName(); // 获取对象的简名、 不包含包名 String simpleName = class1.getSimpleName(); // 获取对象的父类 Class<?> superclass = class1.getSuperclass(); // 获取对象实现的接口 Class<?>[] interfaces = class1.getInterfaces(); // 获取对象的类型名称 String typeName = class1.getTypeName(); // 获取对象的方法 ,不管修饰符,不能获取父类的方法 Method[] methods = class1.getDeclaredMethods(); // 获取对象的public方法,包括父类的方法 Method[] methods2 = class1.getMethods(); for (Method method : methods) { getMethodMSG(method); } // 获取对象所在的包 Package package1 = class1.getPackage(); // 获取对象的成员变量 Field[] fields = class1.getFields(); for (Field field : fields) { getFieldMSG(field); } // 获取自己的构造函数 Constructor<?>[] declaredConstructors = class1.getDeclaredConstructors(); for (Constructor<?> constructor : declaredConstructors) { getConstructorMSG(constructor); } } /** * 获取构造函数的信息 * * @param constructor */ private static void getConstructorMSG(Constructor<?> constructor) { // 获取参数信息 Parameter[] parameters = constructor.getParameters(); // 获取参数的类类型 Class<?>[] parameterTypes = constructor.getParameterTypes(); } /** * 获取成员变量的信息 * * @param field */ private static void getFieldMSG(Field field) { // 获取成员变量的类型 Class<?> type = field.getType(); String name3 = type.getName(); // 获取成员变量的名字 String name2 = field.getName(); } /** * 获取方法的具体信息 * * @param method */ private static void getMethodMSG(Method method) { // 获取方法名 String name2 = method.getName(); // 获取方法的返回类型的类类型 Class<?> returnType = method.getReturnType(); Class<?> declaringClass = method.getDeclaringClass(); // 获取方法参数的类类型 Class<?>[] parameterTypes = method.getParameterTypes(); // 获取方法参数 Parameter[] parameters = method.getParameters(); // 获取方法抛出的的异常类型 Class<?>[] exceptionTypes = method.getExceptionTypes(); // 获取方法的默认值 Object defaultValue = method.getDefaultValue(); }
6.方法反射的应用
通过
method.invoke()方法实现方法的反射
/** * Java反射机制中方法反射 */ private static void methidInvoke() { Student stu = new Student(); //获取class Class<? extends Student> class1 = stu.getClass(); try { //获取方法Method //根据指定的方法名以及参数的类型与个数获取方法 Method method = class1.getMethod("sayHello", String.class); method.invoke(stu, "gaosi"); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } }
7.通过反射了解泛型的本质
泛型是在编译时候效,防止输入错误
ArrayList list = new ArrayList(); ArrayList<String> list1 = new ArrayList<String>(); list1.add("hello"); //list1.add(20);错误的 Class c1 = list.getClass(); Class c2 = list1.getClass(); System.out.println(c1 == c2); //反射的操作都是编译之后的操作 /* * c1==c2结果返回true说明编译之后集合的泛型是去泛型化的 * Java中集合的泛型,是防止错误输入的,只在编译阶段有效, * 绕过编译就无效了 * 验证:我们可以通过方法的反射来操作,绕过编译 */ try { Method m = c2.getMethod("add", Object.class); m.invoke(list1, 20);//绕过编译操作就绕过了泛型 System.out.println(list1.size()); System.out.println(list1); /*for (String string : list1) { System.out.println(string); }*///现在不能这样遍历 } catch (Exception e) { e.printStackTrace(); }