反射reflect

  • 反射的概念
    • 获取字节码文件对象的方式三种
    • class类的方法:
      • 利用calss类方法创建对象的3中方式
    • Constructor构造器的方法:
  • 所有案例演示的主方法和Person类:
      • 案例演示
    • Field类方法结合 (class对象对属性的操作)
      • Field操作成员变量
        • 获取所有成员变量信息
        • 利用反射生成getName方法保存在文件中(放在a.txt中)
    • Method类方法结合 (class对象对方法的操作)
      • Method类的获取
      • Method类的方法:
        • 案例:获取方法名、利用反射调用方法、获取方法数组
    • 反射结合Properties
      • Properties类中的方法
      • 案例演示:
    • 反射结合map生成对象
      • 案例:通过反射 把一个map转成对象

反射的概念

反射:通过Class获取字节码文件对象,使用字节码文件对象来获取类的一些描述信息

  • 成员变量 Field
  • 成员方法 Method
  • 构造方法 Constructor

Java文件 -编译-> 字节码文件 -运行-> JVM执行Class文件(类加载)

类加载

  • 当我们执行java.exe命令,这个字节码文件会被加载到内存当中
  • 同时还会为这个字节码文件创建一个Class的实例

获取字节码文件对象的方式三种

1.Class类中一个静态方法

static Class<?> forName(String className) 方式一的好处: 因为传入的是一个字符串,而这个字符串可以通过配置文件配置满足了设计原则: 开闭原则  对扩展开放,对修改关闭

2.通过数据类型的静态属性 class属性

 *           如果形参需要我们传入Class类型,那么我们可以考虑使用方式二*             public void show(Class c){}*            show(int.class)

3.Object的getClass方法
如下案例:

public class T_getClass {
//获取class对象的3种方法public static void main(String[] args) throws Exception {// TODO Auto-generated method stub//方式一(常用)-------------------------Class<Person> pcla = (Class<Person>) Class.forName("com.ljx.tx0911.Person");System.out.println(pcla);//方式2Class<Person> pcla2=Person.class;System.out.println(pcla2);//方式3Person person=new Person();Class<? extends Person> cla3 = person.getClass();System.out.println(cla3);              }
}

class类的方法:

通过字节码文件对象获取构造方法对象 Constructor

  •     Constructor<?>[] getConstructors() // 获取公有修饰的构造方法对象
    
  •      Constructor<?>[] getDeclaredConstructors() // 获取所有的构造方法对象,含构造
    
  •      Constructor<T> getConstructor(Class<?>... parameterTypes) //获取单个构造方法
    
  •      Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)   //获取私有单个构造方法
    

获取成员变量对象

  •     Field[] getDeclaredFields()  获取所有成员变量对象
    
  •      Field getDeclaredField(String name) 获取指定任意成员变量对象-》获取指定的成员变量,返回类型和名称
    

获取任意方法:

  •     Method dm =pc.getDeclaredMethod("setId", int.class);
    
  •      myc.getDeclaredMethod("service", null);   还有的形参对应的是null  说明service方法没有参数
    
  •      Method[] dms = pc.getDeclaredMethods();//获取所有方法
    

生成Person对象:

  •     pc.newInstance();
    

利用calss类方法创建对象的3中方式

 /** 获取Person对象的三种方式:* 方式1、2步骤:*       1、获取class对象-》class.forname(uri)  *      2、获取特定构造器/构造器数组-》用class的getConstructor(类.class)*        3、获取对象-》用构造器的newInstance* 方式3、步骤:*       1、获取class对象-》class.forname(uri) *       2、获取对象-》用class对象的newInstance();//形参只能是空的,调用的是构造器的newInstance(null)*/
     Class<Person> pc = (Class<Person>) Class.forName("com.ljx.tx0911.Person");Constructor<Person> c = pc.getConstructor(String.class,int.class);//创建对象(有参),对应的是构造方法中的有参           ------------1Person p = c.newInstance("ljx",1);//创建对象(无参),对应的是构造的无参      ----------------------2Constructor<Person> c2 = pc.getConstructor(null);Person p2=c2.newInstance(null);//创建对象,直接用class来创建(实质还是利用无参构造方法对象来创建的) ----------------3Person p3 = pc.newInstance();       System.out.println(p3);System.out.println("--------------------------");

Constructor构造器的方法:

  •    c.toString://打印信息->public com.ljx.tx0911.Person()
    
  •   c.getName():获取构造方法名com.ljx.tx0911.Person
    
  •  c.getParameterCount():对应的方法中形参个数
    
  •  c.getModifiers():权限修饰符  1->public 2->private  4->protected
    

所有案例演示的主方法和Person类:

主方法:只看第四行即可,目的是获取class对象

 public static void main(String[] args) {// TODO Auto-generated method stubtry {Class<Person> pc = (Class<Person>) Class.forName("com.ljx.tx0911.Person");//private java.lang.String com.ljx.tx0911.Person.name //System.out.println(fname);//WriteFanme(fname);//Fieldtest(pc);  getMethods(pc);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}       }

Person类:

public class Person {private String name;private int id;@Overridepublic String toString() {return "Person [name=" + name + ", id=" + id + "]";}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getId() {return id;}public void setId(int id) {this.id = id;}public Person(String name, int id) {super();this.name = name;this.id = id;}public Person() {super();}}

案例演示

public static void test01(Class<Person> pc) throws Exception {Constructor<Person>[] cs = (Constructor<Person>[]) pc.getConstructors();for (Constructor<Person> c : cs) {System.out.println(c);System.out.println(c.getName()+"  "+c.getParameterCount()+"   "+c.getModifiers());//}System.out.println("-------------");/* 打印信息:*  public com.ljx.tx0911.Person()com.ljx.tx0911.Person  0   1public com.ljx.tx0911.Person(java.lang.String,int)com.ljx.tx0911.Person  2   1*/}

Field类方法结合 (class对象对属性的操作)

通过反射获取成员变量对象

利用class对象获取Field的方法:

 * Field[] getFields()  获取公有修饰的成员变量对象-----不用!!* Field[] getDeclaredFields()  获取所有成员变量对象* Field getField(String name) 获取指定的公共成员变量对象--------不用!!* Field getDeclaredField(String name) 获取指定任意成员变量对象-》获取指定的成员变量,返回类型和名称

Field方法:

  • Object get(Object obj) 返回指定对象上此 Field 表示的字段的值。

  • f.getname->获取属性名

  • f.getType->获取属性类型

  • 给对象赋值:set(Object obj, Object value) 例子:f.set(e2, map.get(“name”));//e2为对象,value是String将指定对象变量上此 Field 对象表示的字段设置为指定的新值。(最底下的案例有体现

  • setInt/setChar… (类似上面的函数)

  • 判断是否有注解: f.isAnnotationPresent(myAnnotion.class)

  • 获取注解对象:tostring打印结果@com.ljx.Override.myAnnotion(value=林惊羽)-》在下一章节注解中会详细讲解

Field操作成员变量

获取所有成员变量信息
public static  void Fieldtest(Class<Person> pc) throws Exception{
/**  * Field[] getDeclaredFields()  获取所有成员变量对象* Field getDeclaredField(String name) 获取指定任意成员变量对象-》获取指定的成员变量,返回类型和名称*/        Field[] dfs = pc.getDeclaredFields();for (Field f : dfs) {System.out.println(f);}/*打印信息如下:*  private java.lang.String com.ljx.tx0911.Person.nameprivate int com.ljx.tx0911.Person.id*/}
利用反射生成getName方法保存在文件中(放在a.txt中)
private static void WriteFanme(Field f) {//f:含有Person的name属性以及String类型// TODO Auto-generated method stubStringBuffer sb = new StringBuffer();String name=f.getName();//nameString ftype=f.getType().getName();//java.lang.StringSystem.out.println(name+"  "+ftype);//name  java.lang.StringSystem.out.println("-----------------------------------");sb.append("public  ").append(ftype+"  ").append("get");sb.append(name.substring(0, 1).toUpperCase()).append(name.substring(1)).append("()");sb.append("{\r\n").append("\treturn ").append(name).append(";\r\n}");System.out.println(sb);String s = new String(sb);File fi = new File("a.txt");try {BufferedWriter bw = new BufferedWriter(new FileWriter(fi) );bw.write(s);bw.flush();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}
}

打印信息如下,且分割线之后的代码写入文件中!(这里的StringBuffer转String不熟练!!!)

name  java.lang.String
-----------------------------------
public  java.lang.String  getName(){return name;
}

Method类方法结合 (class对象对方法的操作)

Method类的获取

利用class对象获取如下
class获取方法:

  •     Method dm =pc.getDeclaredMethod("setId", int.class);//class获取任意方法
    
  •      myc.getDeclaredMethod("service", null);   还有的形参对应的是null  说明service方法没有参数
    
  •      Method[] dms = pc.getDeclaredMethods();//获取所有方法
    

利用字节码对象生成Person对象:

  •     pc.newInstance();
    

Method类的方法:

调用方法模板:

  •   invoke(Object obj, Object... args) 对带有指定参数的指定对象调用对应方法
    

调用不带参数的方法(调用加获取)

  •   Method dm = pc.getDeclaredMethod("getId", null);
    
  •   System.out.println(dm.invoke(p, null));
    

调用带参数的方法:(调用加获取)

  •   Method m1 = pc.getDeclaredMethod("setId", int.class);
    
  •   m1.invoke(p, 18);
    

获取方法名称

  •   getName() 以 String 形式返回此 Method 对象表示的方法名称
    

获取所有方法:

  •   Method[] dms = pc.getDeclaredMethods();
    
案例:获取方法名、利用反射调用方法、获取方法数组
 public static void getMethods(Class<Person> pc) throws Exception{Person p = pc.newInstance();Method m1 = pc.getDeclaredMethod("setId", int.class);Method m2=pc.getDeclaredMethod("setName", String.class);m1.invoke(p, 18);m2.invoke(p, "连接线");System.out.println(m1.getName());//setIdSystem.out.println(p);//Person [name=连接线, id=18]Method[] dms = pc.getDeclaredMethods();for (Method m : dms) {System.out.println(m);}}

打印信息:

setId
Person [name=连接线, id=18]
public java.lang.String com.ljx.tx0911.Person.toString()
public java.lang.String com.ljx.tx0911.Person.getName()
public int com.ljx.tx0911.Person.getId()
public void com.ljx.tx0911.Person.setName(java.lang.String)
public void com.ljx.tx0911.Person.setId(int)

反射结合Properties

目的:利用反射获取properties中的类和方法信息,调用该类的方法

Properties类中的方法

(前提条件:先在src下创建reflect.properties)

  •  Properties ps = new Properties();
    
  •  ps加载字节流,读取文件入内存
    
  •  ps.load(new FileInputStream(new File("src/reflect.properties")));获取ps中的配置信息(key->value)
    
  •   String classpath=ps.getProperty("classPath");
    

案例演示:

//目的:利用反射获取properties中的类和方法信息,调用该类的方法public static void main(String[] args) {// TODO Auto-generated method stubProperties ps = new Properties();try {ps.load(new FileInputStream(new File("src/reflect.properties")));String classpath=ps.getProperty("classPath");      String method=ps.getProperty("method");System.out.println(method);//方法一:Class<MyServlet> myc = (Class<MyServlet>) Class.forName(classpath);Constructor<MyServlet> cs = myc.getConstructor(null);MyServlet my = cs.newInstance(null);my.service();//实现调用//方法2:Method m2 = myc.getDeclaredMethod("service", null);m2.invoke(my, null);//实现调用} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}

reflect.properties文件:

classPath=com.ljx.tx0911.MyServlet
method=service

反射结合map生成对象

以下案例有两种方法:建议仔细阅读

  •   方式1  利用方法调用(invoke)-》setId/setName  设置值进对象中
    
  •   //方式2利用Field的set方法将属性注入进对象中(就算是属性是Private修饰也一样能注入!!!!(很强))
    

原因:方式2中f.setAccessible(true);//跳过private安全检查

案例:通过反射 把一个map转成对象

public class T_06reflect {
//通过反射 把一个map转成对象public static void main(String[] args) {// TODO Auto-generated method stubHashMap<String, String> map = new HashMap<>();map.put("id", "001");map.put("name", "张小凡");Emp e =mapToEmp(map);System.out.println(e);      }@Test
private static Emp mapToEmp(HashMap<String, String> map) {// TODO Auto-generated method stubEmp e=null;try {Class<Emp> ec = (Class<Emp>) Class.forName("com.ljx.tx0911.Emp");Constructor<Emp> c = ec.getConstructor();e = c.newInstance();//方式1  利用方法调用(invoke)-》setId/setName  设置值进对象中Method[] dms = ec.getDeclaredMethods();Method m1 = ec.getDeclaredMethod("setId", String.class);Method m2 = ec.getDeclaredMethod("setName", String.class);m1.invoke(e, map.get("id"));m2.invoke(e, map.get("name"));System.out.println(e);//Emp [name=张小凡, id=001]System.out.println("--------------------");//方式2利用Field的set方法将属性注入进对象中(就算是Private修饰也一样能注入!!!!(很强))//通过比较f的name和Person中的name是否一致来向对象设置值Emp e2=ec.newInstance();Field[] fs = ec.getDeclaredFields();for (Field f : fs) {String key=f.getName();         f.setAccessible(true);//跳过private安全检查if(f.getName().equals("name")){f.set(e2, map.get("name"));}if(f.getName().equals("id")){f.set(e2, map.get("id"));}}System.out.println("打印e2:");System.out.println(e2);//Emp [name=张小凡, id=001]} catch (Exception e1) {// TODO Auto-generated catch blocke1.printStackTrace();}return e;
}
}

反射(reflect)应用详解相关推荐

  1. Java基础13:反射与注解详解

    Java基础13:反射与注解详解 什么是反射? 反射(Reflection)是Java 程序开发语言的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性. Orac ...

  2. java反射机制深入详解_Java反射机制深入详解

    原标题:Java反射机制深入详解 一.概念 反射就是把Java的各种成分映射成相应的Java类. Class类的构造方法是private,由JVM创建. 反射是java语言的一个特性,它允程序在运行时 ...

  3. Proxy和Reflect内容详解

    ES6中的Proxy和Reflect内容详解 监听对象的操作 我们先来看一个需求:有一个对象,我们希望监听这个对象中的属性被设置或获取的过程 通过我们前面所学的知识,能不能做到这一点呢? 其实是可以的 ...

  4. java 反射基础 万字详解(Class-Constructor-Method-Field一条龙)

    目录 前言 一.反射及其相关概念 1.什么是反射? 2.反射的用途: ①分析类: ②查看并使用对象: 3.反射的应用场景: 4.类加载器: 类的加载时机: 5.Class对象: 联系: 二.获取Cla ...

  5. ulua中lua代码使用反射调用c#详解

    1.官方解释 2.代码层分析 2.1 官方脚本 2.2 语句 luanet.load_assembly('UnityEngine')解析 LuaState lua = new LuaState(); ...

  6. Java反射机制深入详解

    2019独角兽企业重金招聘Python工程师标准>>> 一.概念 反射就是把Java的各种成分映射成相应的Java类. Class类的构造方法是private,由JVM创建. 反射是 ...

  7. php manual 反射,Laravel框架源码解析之反射的使用详解

    本文实例讲述了Laravel框架源码解析之反射的使用.分享给大家供大家参考,具体如下: 前言 PHP的反射类与实例化对象作用相反,实例化是调用封装类中的方法.成员,而反射类则是拆封类中的所有方法.成员 ...

  8. java反射机制原理详解_java反射机制的详细讲解

    一 , 什么是java反射机制? JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象 ...

  9. java反射机制深入详解_Java基础与提高干货系列——Java反射机制

    前言 今天介绍下Java的反射机制,以前我们获取一个类的实例都是使用new一个实例出来.那样太low了,今天跟我一起来学习学习一种更加高大上的方式来实现. 正文 Java反射机制定义 Java反射机制 ...

  10. Java反射——Type接口详解

    目录 Type的简介 Type的获得 Type的分类 1,Class 2,ParameterizedType 3,GenericArrayType 4,WildcardType 5,TypeVaria ...

最新文章

  1. 控制器框架Struts与策略模式那点事
  2. 年龄估计bridgeNet
  3. android camera2 采集,视频采集:Android平台基于Camera 2的实现
  4. 项目周期一般多久_积木创意:影响小程序开发外包的周期因素有哪些?
  5. 在NT系列操作系统里让自己“消失”
  6. 学到了!程序员大神用这招让开发效率直接提升10倍!!
  7. VMWare tools的安装过程及文件共享设置
  8. paip.验证码识别---初始化
  9. 搜索引擎 —海量数据搜索
  10. 多客技巧分享|【建议收藏】TikTok七大避坑指南帮你少走许多弯路
  11. pc端点击图片放大效果
  12. numpy Week2.2
  13. 阿里云消息队列MQ学习—阿里云大学视频课
  14. 天气预报查询 API + AI 等于王炸(一大波你未曾设想的天气预报查询 API 应用场景更新了)
  15. HTC官方RUU固件提取刷机包rom.zip以及RUU解密教程
  16. 基于PHP+MySQL的学生成绩管理系统——计算机毕业设计
  17. oppo人岗匹配测评_在测试中使用匹配器
  18. 1、Ubuntu下安装软件报错
  19. SD nand 与 SD卡的SPI模式驱动
  20. PC与手机通过有线或无线共享文件或网络

热门文章

  1. 曾经的Uber自动驾驶,其实成败只在一念之间?
  2. 奥特曼和小怪兽的故事
  3. 10款效果惊艳的HTML5应用和源码
  4. wd移动硬盘测试软件,让你的秘密高枕无忧 WD My Passport随行版移动硬盘评测
  5. day 5 文字溢出处理 背景图片处理 开发经验
  6. 性能分析之TPS从300到750的过程
  7. 如何改变Visual Studio的桌布背景颜色(手把手保姆级教程)
  8. 【ABAP】创建局部Macro和全局Macro
  9. 自律,是爱自己的最好方式!
  10. android 原型图片,丑小鸭外传:一台来自2007年的Android原型机图赏