首页 > 学院 > 开发设计 > 正文

反射

2019-11-09 16:26:07
字体:
来源:转载
供稿:网友

反射

获得对象

public class ClassDemo1 { public static void main(String[] args) { /** * Foo的实例对象如何表示 * foo1就表示出来了 */ Foo foo1 = new Foo(); /** * Foo这个类也是一个实例对象,Class类的实例对象 * 如何表示 * 任何一个类都是Class类的实例对象 * 这个实例对象有三种表示方式 */ /** * [1] 任何一个类都有一个隐含的静态成员变量Class */ Class c1 = Foo.class; /** * [2] 已知改类的对象,通过getClass方法 */ Class c2 = foo1.getClass(); /** * c1,c2表示了Foo类的类类型(class type) * 类也是对象,是Class类的实例对象 * 这个对象我们称为改类的类类型 */ /** * 不管c1 or c2都代表了Foo类的类类型,一个类只可能是 * Class类的一个实例对象 */ System.out.PRintln(c1==c2); //true /** * [3] 通过类的全称获得 */ Class c3 = null; try { c3 = Class.forName("com.shixin.Foo"); } catch (ClassNotFoundException e) { System.out.println("类未找到"); } System.out.println(c2==c3); //true /** * 我们完全可以通过类的类类型创建该类的对象实例 * 需要有无参的构造方法 */ try { Foo foo = (Foo) c1.newInstance(); foo.print(); } catch (Exception e) { } }}class Foo{ void print(){ System.out.println("Foo:测试"); }}

动态加载

类是对象,类是java.lang.Class类的实例对象 这里写图片描述

package com.bean;// 创建一个协商好的接口public interface IWordAble { public void start();}package com.bean;// 实现接口public class Excel implements IwordAble{ @Override public void start() { System.out.println("启动文档"); System.out.println("结束文档"); }}package com.bean;// 实现接口public class Word implements IwordAble{ // 成员变量 public int aaa; public int bbb; @Override public void start() { System.out.println("世界开始"); System.out.println("世界结束"); } public void cond(int n){ // 方法1 } public Word(){ // 无参构造方法 } public Word(int a){ // 有参构造方法 }}package com.shixin;import com.bean.IwordAble;public class ClassDemo2 { public static void main(String[] args) { /** * Class.forName("类的全称"); * 不仅表示了类的类类型,还代表了动态加载类 * 编译时刻加载类是静态加载类 * 运行时刻加载类是动态加载类 */ /** * new 对象是静态加载类 * 在编译时刻就需要加载所有可能使用到的类 * 通过动态加载类可以解决这个问题 */ // Word w = new Word(); 没有导包的话会报错 try { // 使用动态加载 Class w = Class.forName("com.bean.Word"); // 通过类类型创建创建类对象 // 强转成协商好的接口 IwordAble iw = (IwordAble) w.newInstance(); iw.start(); Class ex = Class.forName("com.bean.Excel"); // 通过类类型创建创建类对象 // 强转成协商好的接口 IwordAble iex = (IwordAble) ex.newInstance(); iex.start(); } catch (Exception e) { } }}

这里写图片描述

工具类:

public class ClassUtils { /** * 打印类的信息 * 包括累的成员函数、成员变量 * @param obj 该对象所属类的信息 */ public static void printClassMessage(Object obj){ /** * 要获取类的信息 * 首先要获取类的类类型 * 传递的是哪个子类的对象 * c就是该子类的类类型 */ Class c = obj.getClass(); /** * 获取类的名称 */ System.out.println("类的名称是: "+c.getName()); /** * 获取类的方法信息 */ printMethodMessage(c); /** * 获取类的成员信息 */ printFieldMessage(c); /** * 获取构造方法的信息 */ printConstructorMessage(c); }}

获取方法信息

private static void printMethodMessage(Class c) { /** * Method类 方法的对象 * 一个成员方法就是一个Method类 * getMethods获取的是所有public的方法,包括父类继承而来的方法 * getDeclaredMethods获取的该类自己声明的方法 */ Method[] ms = c.getMethods(); Method[] ms2 = c.getDeclaredMethods(); for(int i=0; i<ms.length; i++){ // 得到方法的返回值类型 String returnType = ms[i].getReturnType().getName(); // 得到方法的名称 String name = ms[i].getName(); // 获取参数类型---得到的是参数列表的类型的类类型 Class[] parameterTypes = ms[i].getParameterTypes(); StringBuilder sb = new StringBuilder(); for (Class class1 : parameterTypes) { String p = class1.getName(); sb.append(p).append(" "); } String param = sb.toString(); System.out.println("该类的第"+i+"个方法是" +returnType+" "+name +"( "+param+")"); } }public class Test { public static void main(String[] args) { Word w = new Word(); ClassUtils.printClassMessage(w); }}

这里写图片描述

获取成员信息

private static void printFieldMessage(Class c) { System.out.println("成员变量:"); /** * 成员变量也是对象 * java.lang.reflact.Field * Field类封装了关于成员变量的操作 * getFields()方法获取的是所有public的成员变量的信息 * getDeclaredFields()获取的是该类自己声明的成员变量的信息 * */ Field[] fs = c.getFields(); Field[] df = c.getDeclaredFields(); for (int i = 0; i < df.length; i++) { // 得到成员变量的类型的类类型 Class fieldType = df[i].getType(); String typeName = fieldType.getName(); // 得到成员变量的名称 String fileName = df[i].getName(); System.out.println(typeName+" "+fileName); } }

获取构造方法信息

private static void printConstructorMessage(Class c) { System.out.println("构造方法:"); /** * 构造方法也是对象 * java.lang.Constructor中封装了构造方法的信息 * getConstructors获取所有的公有构造方法 * getDeclaredConstructors获得所有自己的构造方法 */ Constructor[] cs = c.getConstructors(); Constructor[] cs2 = c.getDeclaredConstructors(); for (int i = 0; i < cs2.length; i++) { String constructorName = cs2[i].getName(); // 获取构造方法的参数列表 Class[] paramTypes = cs2[i].getParameterTypes(); StringBuffer sb = new StringBuffer(); for (Class class1 : paramTypes) { String typeName = class1.getName(); sb.append(typeName).append(" "); } System.out.println(constructorName +"(" +sb.toString()+")"); } }

这里写图片描述

反射的基本操作

package com.shixin;import java.lang.reflect.Method;public class MethodDemo1 { public static void main(String[] args) { /** * 反射的基本操作 */ /** * 如何获取某个方法? * 方法的名称和方法的参数列表此案能唯一决定某个方法 * 方法的反射操作 * method.invoke(对象,参数列表) */ // 获取print(int,int)方法 /** * 要获取一个方法就是获取类的信息 * 获取类的信息首先要获取类的类类型 * 获取方法 名称和参数列表来决定 * getMethod获取的是public的方法 * getDeclaredMethods获取自己声明的方法 * */ A a1 = new A(); Class c = a1.getClass(); try { Method m = c.getMethod("print", new Class[] { int.class, int.class }); //Method[] dm = c.getDeclaredMethods(); /** * 方法的反射操作 */ //a1.print(10, 20); 方法的反射操作指的是用m对象来进行方法调用 // 和a1.print的效果完全相同 // 方法如果没有返回值返回null,有返回值返回具体的返回值 Object o = m.invoke(a1, new Object[]{10,20}); // 30 Method m2 = c.getMethod("print", new Class[] { String.class, String.class }); Object o2 = m2.invoke(a1, new Object[]{"QQq","DDD"}); // QQQ,ddd Method m3 = c.getMethod("print", new Class[]{}); m3.invoke(a1,new Class[]{}); } catch (Exception e) { } }}class A{ public void print(){ System.out.println("hello world"); } public void print(int a, int b){ System.out.println(a + b); } public void print(String a, String b){ System.out.println(a.toUpperCase()+","+b.toLowerCase()); }}

这里写图片描述

通过反射了解集合泛型的本质

public class MethodDemo2 { public static void main(String[] args) { ArrayList list = new ArrayList(); ArrayList<String> list1 = new ArrayList<>(); list1.add("hello"); Class c1 = list.getClass(); Class c2 = list1.getClass(); System.out.println(c1==c2); // true /** * 反射的操作都是编译之后的操作 * c1==c2结果返回true说明编译之后集合的泛型是去泛型化的 * java中集合的泛型,是防止错误输入的,只在编译阶段有效 * 绕过编译就无效了 * 验证: 我们可以通过方法的反射来操作, 绕过编译 * 绕过编译就绕过了泛型 */ try { Method m = c2.getMethod("add", Object.class); m.invoke(list1,100); System.out.println("此时list的长度为:"+list1.size()); // 2 System.out.println(list1); // [hello, 100]// for (String string : list1) {// System.out.println(string);// } // 现在就不能这样遍历了 } catch (Exception e) { } }}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表