Java工作笔记-对反射的进一步理解
发布日期:2021-06-30 10:41:03
浏览次数:2
分类:技术文章
本文共 8446 字,大约阅读时间需要 28 分钟。
目录
基本概念
反射的进一步理解:
将类的各个组成部分封装为其他对象(将一个类的组成部分封装为其他对象) 就是反射。
Java代码经历的三个阶段:
1. 写好代码.java后使用javac,编译为字节码文件:xxx.class 这个阶段称之为source源代码阶段。 3. 当程序要new一个对象时 这个阶段称之为Runtime运行时阶段 2. 把字节码文件.class加载进内存里面(使用类加载器ClassLoader) 在内存里面会存在一个对象用于描述字节码文件。这个对象为Class对象。 所以java里面有个Class类。专门用来搞这个字节码文件的 如: 成员变量(Fields)、构造方法(Constructor)、成员方法(Method) 这个阶段称之为Class类对象阶段
第三阶段都是同过第二阶段创建起来的。第二个阶段需要第一个阶段。
反射好处:
1. 在程序运行过程中操作这些对象。(IDEA这个程序的 某个对象方法的提示,就是反射) 2. 可以解耦。提高程序可扩展性。
获取Class对象的方式:
有3种方式,对应java代码经历的3个阶段; 第一个阶段只有.class字节码文件,并没有在内存中,要把.class加载到内存中生成对象。对应的API为:Class.forName("全类名") 返回class对象; 第二个阶段:这个.class字节码文件已经到内存了,这个时候,只要获取他就可以了,类名.class,这种方式。 第三个阶段:在Runtime时,已经有对象了,这个时候只要 对象.getClass()就可以了。这个getClass()类是在Object里面 的。
总结下:
1.Class.forName("全类名");将字节码文件加载到内存,返回class对象。 2.类名.class;通过类名的属性class获取。 3.对象.getClass();getClass()方法在Object类中定义
代码与实例
如下代码:
Person.java
package Object;public class Person { private String name; private Integer age; public Person(String name, Integer age) { this.name = name; this.age = age; } public Person(){ } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; }}
Main1.java
import Object.Person;public class Main1 { public static void main(String[] args) throws ClassNotFoundException { //全类名 Class cls1 = Class.forName("Object.Person"); System.out.println(cls1); //类名.class Class cls2 = Person.class; System.out.println(cls2); //对象.getClass() Person p = new Person(); Class cls3 = p.getClass(); System.out.println(cls3); //比较下对象: System.out.println(cls1 == cls2); System.out.println(cls1 == cls3); }}
程序运行截图如下:
结论:
同一个字节码文件.class在一次程序运行过程中,只会被加载一次,不论通过哪种方式获取的class对象都是同一个。 第一种方式,多用于配置文件中,读取文件,加载类 第二种方式,多用于参数的传递; 第三种方式,多用于对象的获取字节码下面是
Class对象功能:
1.获取成员变量; Field[] getFields() Field getField(String name) Field[] getDeclaredFields() Field getDeclaredField(String name) 2.获取构造方法; Constructor<?>[] getConstructors() Constructor<T> getConstructor(类<?>... parameterTypes) Constructor<T> getDeclaredConstructor(类<?>... parameterTypes) Constructor<?>[] getDeclaredConstructors() 3.获取成员方法; Method[] getMethods() Method[] getMethod(String name, 类<?>... parameterTypes) Method[] getDeclaredMethods() Method getDeclaredMethod(String name, 类<?>... parameterTypes) 4.获取类名; String getName()
下面先给出变量名的实例
Person.java
package Object;public class Person { private String name; private Integer age; public String a; protected String b; String c; private String d; public Person(String name, Integer age) { this.name = name; this.age = age; } public Person(){ } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + ", a='" + a + '\'' + ", b='" + b + '\'' + ", c='" + c + '\'' + ", d='" + d + '\'' + '}'; }}
Main2.java
import Object.Person;import java.lang.reflect.Field;public class Main2 { public static void main(String[] args) throws Exception { //Field[] getFields()获取所有public修饰的成员变量 Class aClass = Class.forName("Object.Person"); Field[] fields = aClass.getFields(); for(Field field : fields){ System.out.println(field); } //获取及设置a的值 Field a = aClass.getField("a"); Person person = new Person(); Object value = a.get(person); System.out.println("the a is : " + value); a.set(person, "你妹"); System.out.println(person); System.out.println("----------华丽的分割线----------"); //Field getDeclaredField(String name) Field[] declaredFields = aClass.getDeclaredFields(); for(Field field : declaredFields){ System.out.println(field); } //忽略修饰符暴力反射,设置值 Field d = aClass.getDeclaredField("d"); d.setAccessible(true); d.set(person, "猪小明"); System.out.println(person); }}
运行截图如下:
下面是关于构造函数的反射:
Person还是与上面的一样。
import Object.Person;import java.lang.reflect.Constructor;public class Main3 { public static void main(String[] args) throws Exception { Class personClass = Person.class; Constructor constructor = personClass.getConstructor(String.class, Integer.class); System.out.println(constructor); //创建对象 Object p = constructor.newInstance("王二麻子", 99); System.out.println(p); System.out.println("----------华丽的分割线----------"); Constructor constructor2 = personClass.getConstructor(); Object p2 = constructor2.newInstance(); System.out.println(p2); }}
程序运行截图如下:
下面是获取成员方法的实例。
Person.java
package Object;public class Person { private String name; private Integer age; public String a; protected String b; String c; private String d; public Person(String name, Integer age) { this.name = name; this.age = age; } public Person(){ } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + ", a='" + a + '\'' + ", b='" + b + '\'' + ", c='" + c + '\'' + ", d='" + d + '\'' + '}'; } public void eat(){ System.out.println("eat... ..."); } //带参数的 public void eat(String food){ System.out.println("eat... ..." + food); }}
Main4.java
import Object.Person;import java.lang.reflect.Method;public class Main4 { public static void main(String[] args) throws Exception { Class personClass = Person.class; //获取指定名称的方法 Method eat = personClass.getMethod("eat"); Person p = new Person(); eat.invoke(p); System.out.println("----------华丽的风格线----------"); Method eat1 = personClass.getMethod("eat", String.class); eat1.invoke(p, "西北风"); //获取所有Public修饰的方法 Method[] methods = personClass.getMethods(); for(Method method : methods){ System.out.println(method); String name = method.getName(); System.out.println(name); //method.setAccessible(true); } }}
程序运行截图如下:
下面是关于获取类名的实例:
Main5.java
import Object.Person;public class Main5 { public static void main(String[] args){ Class personClass = Person.class; System.out.println(personClass.getName()); }}
程序运行截图如下:
import Object.Person;public class Main5 { public static void main(String[] args){ Class personClass = Person.class; System.out.println(personClass.getName()); }}
程序运行截图如下:
下面来仿一个案例,像Spring Boot那样的通过配置application.properties既可以调用相应的类,和函数
这里应用到的就是反射
Main6.java
import Object.Person;import java.io.InputStream;import java.lang.reflect.Method;import java.util.Properties;public class Main6 { public static void main(String[] args) throws Exception { /*** * 加载配置文件 * 创建Properties对象 * 加载配置文件,转换为集合 * 获取class目录下的配置文件 */ Properties pro = new Properties(); ClassLoader classLoader = Person.class.getClassLoader(); InputStream resourceAsStream = classLoader.getResourceAsStream("application.properties"); pro.load(resourceAsStream); //配置文件中定义的数据 String className = pro.getProperty("className"); String methodName = pro.getProperty("methodName"); //加载该类到内存 Class aClass = Class.forName(className); Object o = aClass.newInstance(); //获取方法并执行 Method method = aClass.getMethod(methodName); method.invoke(o); }}
通过这种配置文件,即可调用对应的类和方法:
程序运行截图如下:
源码打包下载地址:
转载地址:https://it1995.blog.csdn.net/article/details/103556575 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
表示我来过!
[***.240.166.169]2024年04月25日 12时35分38秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
基于java的魂斗罗的设计
2019-04-30
基于java的网页内容管理
2019-04-30
基于java的学生管理系统
2019-04-30
基于java网盘搜索的设计与实现
2019-04-30
基于SSM的仿小米商城源码
2019-04-30
基于SSM的医院人事管理系统的设计与实现
2019-04-30
基于SSM的兼职论坛系统的设计与实现
2019-04-30
基于java的图书管理系统的设计与实现
2019-04-30
基于java的SSM框架理财管理系统的设计与实现
2019-04-30
基于java的ssm框架就业信息管理系统的设计
2019-04-30
基于java的ssm框架的旅游网站设计与实现
2019-04-30
基于java的SSM框架的流浪猫救助网站的设计与实现
2019-04-30
基于java的SSM框架的教务关系系统的设计与实现
2019-04-30
别再问我什么是A/B测试了!
2019-04-30
如何用同期群分析模型提升留存?(Tableau实战)
2019-04-30
爱了,吹爆这个高颜值的流程图工具!
2019-04-30
一个数据项目
2019-04-30
java的酒店房间管理系统
2019-04-30
基于Java的截图工具
2019-04-30
基于JAVA的停车场管理系统
2019-04-30