反射(reflect)应用详解
反射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)应用详解相关推荐
- Java基础13:反射与注解详解
Java基础13:反射与注解详解 什么是反射? 反射(Reflection)是Java 程序开发语言的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性. Orac ...
- java反射机制深入详解_Java反射机制深入详解
原标题:Java反射机制深入详解 一.概念 反射就是把Java的各种成分映射成相应的Java类. Class类的构造方法是private,由JVM创建. 反射是java语言的一个特性,它允程序在运行时 ...
- Proxy和Reflect内容详解
ES6中的Proxy和Reflect内容详解 监听对象的操作 我们先来看一个需求:有一个对象,我们希望监听这个对象中的属性被设置或获取的过程 通过我们前面所学的知识,能不能做到这一点呢? 其实是可以的 ...
- java 反射基础 万字详解(Class-Constructor-Method-Field一条龙)
目录 前言 一.反射及其相关概念 1.什么是反射? 2.反射的用途: ①分析类: ②查看并使用对象: 3.反射的应用场景: 4.类加载器: 类的加载时机: 5.Class对象: 联系: 二.获取Cla ...
- ulua中lua代码使用反射调用c#详解
1.官方解释 2.代码层分析 2.1 官方脚本 2.2 语句 luanet.load_assembly('UnityEngine')解析 LuaState lua = new LuaState(); ...
- Java反射机制深入详解
2019独角兽企业重金招聘Python工程师标准>>> 一.概念 反射就是把Java的各种成分映射成相应的Java类. Class类的构造方法是private,由JVM创建. 反射是 ...
- php manual 反射,Laravel框架源码解析之反射的使用详解
本文实例讲述了Laravel框架源码解析之反射的使用.分享给大家供大家参考,具体如下: 前言 PHP的反射类与实例化对象作用相反,实例化是调用封装类中的方法.成员,而反射类则是拆封类中的所有方法.成员 ...
- java反射机制原理详解_java反射机制的详细讲解
一 , 什么是java反射机制? JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象 ...
- java反射机制深入详解_Java基础与提高干货系列——Java反射机制
前言 今天介绍下Java的反射机制,以前我们获取一个类的实例都是使用new一个实例出来.那样太low了,今天跟我一起来学习学习一种更加高大上的方式来实现. 正文 Java反射机制定义 Java反射机制 ...
- Java反射——Type接口详解
目录 Type的简介 Type的获得 Type的分类 1,Class 2,ParameterizedType 3,GenericArrayType 4,WildcardType 5,TypeVaria ...
最新文章
- 控制器框架Struts与策略模式那点事
- 年龄估计bridgeNet
- android camera2 采集,视频采集:Android平台基于Camera 2的实现
- 项目周期一般多久_积木创意:影响小程序开发外包的周期因素有哪些?
- 在NT系列操作系统里让自己“消失”
- 学到了!程序员大神用这招让开发效率直接提升10倍!!
- VMWare tools的安装过程及文件共享设置
- paip.验证码识别---初始化
- 搜索引擎 —海量数据搜索
- 多客技巧分享|【建议收藏】TikTok七大避坑指南帮你少走许多弯路
- pc端点击图片放大效果
- numpy Week2.2
- 阿里云消息队列MQ学习—阿里云大学视频课
- 天气预报查询 API + AI 等于王炸(一大波你未曾设想的天气预报查询 API 应用场景更新了)
- HTC官方RUU固件提取刷机包rom.zip以及RUU解密教程
- 基于PHP+MySQL的学生成绩管理系统——计算机毕业设计
- oppo人岗匹配测评_在测试中使用匹配器
- 1、Ubuntu下安装软件报错
- SD nand 与 SD卡的SPI模式驱动
- PC与手机通过有线或无线共享文件或网络