JAVA--reflect(反射)
来源:互联网 发布:环保部网络举报 编辑:程序博客网 时间:2024/06/14 01:02
java编程之ReFlect(反射)
- Class类的反射
- 方法的反射
- 成员变量的反射
- 构造函数的反射
java类加载机制
Class类的反射
Class类
在面向对象的世界里,万事万物都是对象。
java语言中,静态的成员,普通的数据类型也是对象,类的实例就是类的对象。
那么类是谁的对象呢?
类是对象,类是java.lang.Class类的实力对象。
There is a class named Class
package com.imooc.ReFlectTest;/***这段代码介绍了关于Class类的实例的三种创建方法*/public class ClassDemo1 { public static void main(String[] args) { //创建一个Dog类的实例对象 Dog dog = new Dog(); //Dog类也是实例对象,Dog类是Class类的实例对象 //Class类只有private权限的构造函数,只允许jvm调用! //我Class类的实例对象,一共有3种表示方式 //第一种每个类都有一个隐含的static(静态)的成员class,可以直接调用 Class c1 = Dog.class; //第二种,已知一个类的实例对象,可以调用getClass()方法 Class c2 = dog.getClass(); /** * 官方上给的解释,此处的c1,c2是Dog类的(class type(类类型)) */ //结果是true,说明c1,c2都代表了Dog类的类类型,也说明了一个类只有一个Class类的一个实例对象 System.out.println(c1 == c2); //第三种方式,调用Class类的forName方法,会有异常 Class c3 = null; try { //方法中写入类的全称 c3 = Class.forName("com.imooc.ReFlectTest.Dog"); } catch (ClassNotFoundException e) { e.printStackTrace(); } //此处依然是true,还是那句话一个类只有一个Class类的实例对象 System.out.println(c2 == c3); /** * 我们也可以通过类的类类型来创建该类的实例 * 即我们可以用c1 or c2 or c3 来创建一个Dog类的对象 */ try { //类类型创建的类的实例是Object类型的,此处因为没有用泛型,所以我们需要进行强制类型转换 //前提是该类要有无参数的构造方法 Dog dog1 = (Dog)c1.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } }}class Dog{}
Class.forName(“类的全称”)
- 不仅表示类的类类型,还表示了动态加载类
- 区分编译和运行
- 编译时加载的类是静态加载类,运行时加载的类是动态加载类
使用反射访问类的所有信息
代码中的注释已经详细解释了他们的作用
package com.imooc.ReFlectTest;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;public class Classutil { /** * 打印类的信息,包括类的成员函数的信息 * obj 即类的对象,此处没用泛型,所以用多态来实现 */ public static void printClassMassage(Object obj) { //获取实际传递的obj的类类型 Class c = obj.getClass();//存在多态,实际调用时,调用的是传递的类的方法 //获取类的名字 System.out.println(c.getName()); /** * Method方法,用来获取类的方法名 * 一个方法就是一个Method对象 * getMethods()方法获取的是所有的public的函数,包括从父类继承来的 * getDeclaredMethods()方法获取类自己声明的所有方法,不问访问权限 */ Method[] methods = c.getMethods();//c.getDeclaredMethods(); for(int i=0; i<methods.length; i++) { //输出方法的名字 System.out.print(methods[i].getName() + "("); //通过方法,获取方法的参数列表 //getParameterType()方法,获取参数列表的类型的类类型 Class[] parameterType = methods[i].getParameterTypes(); //依次打印方法的参数列表 for (Class class1 : parameterType) { System.out.print(class1.getName() + ","); } System.out.println(")"); } } public static void printFieldMessage(Object obj) { Class c = obj.getClass(); /** * 获取类的成员变量的信息 * 用java.lang.reflect.Field * Field封装了关于类的成员变量的所有操作 * getFileds()方法获取所有权限为public的成员变量的信息 * getDeclaredFileds()方法获取的是该类自己声明的变量的信息 */ Field[] fileds = c.getDeclaredFields(); for (Field field : fileds) { //得到成员变量的类型的类类型 Class fieldType = field.getType(); //typeName,成员变量的名字,即变量名 String typeName = fieldType.getName(); //fieldName,变量的类类型的名字,即变量的类型名(例:int,String) String fieldName = field.getName(); System.out.println("typeName = " + typeName + " " +"fieldName = "+ fieldName); } } public static void printConMessage(Object obj) { Class c = obj.getClass(); //获取所有的public的构造方法 //Constructor[] cs = c.getConstructors(); //获取当前类内的所有的构造方法Constructor Constructor[] cs = c.getDeclaredConstructors(); for (Constructor constructor : cs) { System.out.print(constructor.getName() + "("); Class[] parameter = constructor.getParameterTypes(); for (Class class1 : parameter) { System.out.print(class1.getName() + ","); } System.out.println(")"); } }}
通过上述代码的方法,我们可以访问任意一个类的名称以及它的所有方法的名称,参数列表以及返回值,包括构造函数!
当然除了上述的三种访问以外,reflect中还封装了很多很好的方法,我们可以在需要的时候,去查阅java.lang,Class的API
通过获取的类信息,可以做反射操作
我们通过获取的类的信息,可以方法调用对象
package com.imooc.ReFlectTest;import java.lang.reflect.Method;public class ClassDemo5 { public static void main(String[] args) { A a1 = new A(); //获取方法的信息的前提是获取类的信息,获取类的信息要先获取类的类类型 Class c = a1.getClass(); try { /** * 获取方法,由名称和参数列表来决定 * getMethod()获取public的方法 * getDeclaredMethod()获取自己声明的方法 */ Method m = c.getMethod("print", int.class, int.class); //方法的反射调用,利用m对象进行方法的调用invoke()方法,和a1.print()的效果完全相同 //invoke(obj, new Object[]) //方法无返回值,则返回null,否则返回方法的返回值 Object o = m.invoke(a1, new Object[]{10,20});// Object o = m.invoke(a1, 10,20); System.out.println("================================"); Method m1 = c.getMethod("printStr", String.class, String.class); //用方法进行反射操作// a1.printStr("Hello", "World"); m1.invoke(a1, "hello", "World"); System.out.println("================================="); //方法没有参数 //方法1 ,传一个空的类类型数组// Method m2 = c.getMethod("print", new Class[]{}); //方法2,不穿参数也可以 Method m2 = c.getMethod("print");// m2.invoke(a1, new Object[]{}); m2.invoke(a1); } catch (Exception e) { e.printStackTrace(); } }}class A { public void print(int a, int b) { System.out.println(a + b); } public void printStr(String a, String b) { System.out.println(a.toUpperCase() + "," + b.toUpperCase()); }}
通过反射我们可以理解集合泛型的本质
泛型的目的是为了防止输入错误,但只在编译时有效。
package com.imooc.ReFlectTest;import java.awt.event.FocusEvent;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.List;public class ClassDemo6 { public static void main(String[] args) { List l1 = new ArrayList(); List<String> l2 = new ArrayList<String>(); Class c1 = l1.getClass(); Class c2 = l2.getClass(); //结果为true System.out.println(c1 == c2); l2.add("hello"); //String类型的List不能添加int型的数,编译时无法通过// l2.add(20); /** * 反射的操作都是编译之后的操作 * c1 == c2 返回值为true说明编译之后的集合是“去泛型化”的 * java集合中的泛型,是防止错误输入的,只在编译阶段有效 * 当我们绕过编译时,泛型就无效了 * 验证:通过方法的反射操作,绕过编译 */ try { Method m = c2.getMethod("add", Object.class); m.invoke(l2, 20); System.out.println(l2.size()); System.out.println(l2); /* * 不能使用foreach循环,会出异常 * for (String string : l2) { * System.out.println(string); * } */ } catch (Exception e) { e.printStackTrace(); } }}
0 0
- java 反射机制 reflect
- java反射机制reflect
- Java 反射,reflect
- Java reflect 反射
- java reflect 反射
- java反射reflect
- Java反射机制(reflect)
- java reflect反射总结
- java反射reflect
- java 反射 reflect
- JAVA--reflect(反射)
- Java反射实例-Reflect
- Java反射(reflect)
- Java反射Reflect
- Reflect Java反射机制
- Java-反射机制reflect
- java reflect:反射机制
- Java反射reflect
- 项目2 -- 建立链栈算法库
- 第七周项目二建立链队算法库
- 第七周上机实践项目3——负数把正数赶出队列
- 第七周上机实践—项目3—负数把正数赶出队列
- hadoop 文件目录操作
- JAVA--reflect(反射)
- centos7上搭建docker私有仓库
- Eclipse 工程项目报错Target runtime com.genuitec.runtime.generic.jee60 is not defined
- 第四周项目4建设双链表算法库
- 第四周 建立双链表的算法库
- 第四周项目3—单链表应用(2)
- 第七周--负数把正数赶出队列
- 一点一滴掌握WPF应用系列 - 画刷使用(1):SolidColorBrush、LinearGradientBrush、RadialGradientBrush
- ThreadLocal浅析