反射
2022/8/6 23:23:28
本文主要是介绍反射,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
反射:运行时动态访问类与对象的技术
创建对象的时间 从编译时变成运行时
反射的作用:
package fnshe; /** *接口 / public interface Math { public float ss(float a,float b); }
package fnshe; /** *ADD实现 **/ public class ADD implements Math{ @Override public float ss(float a, float b) { return a+b; } }
package fnshe; /** *实现接口 **/ public class CHEN implements Math{ @Override public float ss(float a, float b) { return a*b; } }
package fnshe; /** *实现接口 **/ public class CHU implements Math { @Override public float ss(float a, float b) { if(b!=0){ return a/b; }else { throw new RuntimeException("出书不能为0"); } } }
package fnshe; /** *实现接口 **/ public class JIAN implements Math{ @Override public float ss(float a, float b) { return a-b; } }
package fnshe; import java.util.Scanner; /** *操作类 **/ public class Application { public void caozuo() throws ClassNotFoundException, InstantiationException, IllegalAccessException { Scanner scanner = new Scanner(System.in); String op = scanner.nextLine(); float a=scanner.nextFloat(); float b=scanner.nextFloat(); Math o=(Math)Class.forName("fnshe."+op).newInstance();//动态创建对象 System.out.println(o.ss(a, b)); } public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { Application application = new Application(); application.caozuo(); } }
反射的四个核心类
1.Class类
2.Constructor构造方法类
3.Method类
4.Field成员变量类
Class是JVM中代表”类和接口“的类
Class对象具体包含了某个特定类的结构信息
通过Class对象可获取对应类的构造方法/方法/成员变量
Class类核心方法
方法 | 用途 |
---|---|
Class.forName() | 静态方法,用于获取指定Class对象 |
classObj.newInstance() | 通过默认构造方法创建新的对象 |
classObj.getConstructor() | 获得指定的public修饰构造方法Constructor对象 |
classObj.getMethod() | 获取指定的public修饰方法Method对象 |
classObj.getFiled() | 获取指定的public修饰成员变量Field对象 |
Constructor构造方法类
Constructor类时对java类中的构造方法的抽象
Contructor对象包含了具体类的某个构造方法的声明
通过Constructor对象调用带参构造方法创建对象
核心方法
方法 | 用途 |
---|---|
classObject.getConstructor() | 获取指定public修饰的构造方法对象 |
constructorObj.newInstance() | 通过对应的构造方法创建对象 |
Method方法类
方法 | 用途 |
---|---|
classObj.getMethod() | 获取指定public修饰的方法对象 |
methodObj.invoke() | 调用指定对象的对应方法 |
Field成员变量类
Field对应某个具体类中的成员变量的声明
Field对象使用classObj.getField()方法获取
通过Field对象可为某对象成员变量赋值/取值
方法 | 用途 |
---|---|
classObj.getField() | 获取指定public修饰的成员变量 |
fieldObj.set() | 为某对象指定成员变量赋值 |
fieldObj.get() | 获取某对象指定成员变量数值 |
getDeclared系列方法
getDeclaredConstructors(s)|method(s)|Field(s)获取对应对象
访问非作用域,会抛出异常
代码
package reflect.entity; import javax.jws.soap.SOAPBinding; /** *Employee类 **/ public class Employee { static { System.out.println("Employee类已经被加载到jvm,并初始化"); } private Integer eno; public String ename; private Float salary; private String dname; public Employee() { System.out.println("Employee默认方法被执行..."); } //注意点,所有参数类型都是引用类型 public Employee(Integer eno, String ename, Float salary, String dname) { this.eno = eno; this.ename = ename; this.salary = salary; this.dname = dname; System.out.println("Employee带参方法被执行..."); } public Integer getEno() { return eno; } public void setEno(Integer eno) { this.eno = eno; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public Float getSalary() { return salary; } public void setSalary(Float salary) { this.salary = salary; } public String getDname() { return dname; } public void setDname(String dname) { this.dname = dname; } @Override public String toString() { return "Employee{" + "eno=" + eno + ", ename='" + ename + '\'' + ", salary=" + salary + ", dname='" + dname + '\'' + '}'; } //注意点,所有参数类型都是引用类型 public Employee updateSalary(Float val){ this.salary=this.salary+val; System.out.println("调整薪资为"+this.salary+"元"); return this; } }
package reflect; import reflect.entity.Employee; /** *创建对象 **/ public class ClassSample { public static void main(String[] args) { //Class.forName()方法将指定的类加载到jvm,并返回对应Class对象 //employeeClass包含reflect.entity.Employee所有成员 try { Class employeeClass=Class.forName("reflect.entity.Employee"); System.out.println("Employee已被加载到jvm"); //newInstance()通过默认构造器创建新的对象 Employee employee= (Employee)employeeClass.newInstance(); /** * 执行结果 * Employee类已经被加载到jvm,并初始化 * Employee已被加载到jvm * Employee默认方法被执行... */ } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { //实例化异常,抽象类,接口 e.printStackTrace(); } catch (IllegalAccessException e) { //访问权限异常,当在作用域外访问对象方法或成员变量时抛出 e.printStackTrace(); } } }
package reflect; import reflect.entity.Employee; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; /** *构造反方法 **/ public class ConstructorSample { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { Class employeeClass=Class.forName("reflect.entity.Employee"); //选定特定构造器 Constructor constructor = employeeClass.getConstructor(new Class[]{ Integer.class, String.class, Float.class, String.class }); //给构造器传值 Employee employee = (Employee)constructor.newInstance(new Object[]{ 100, "李磊", 300f, "研发部" }); System.out.println(employee);//Employee{eno=100, ename='李磊', salary=300.0, dname='研发部'} } }
package reflect; import reflect.entity.Employee; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * 方法 **/ public class MethodSample { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { Class employeeClass=Class.forName("reflect.entity.Employee"); Constructor constructor = employeeClass.getConstructor(new Class[]{ Integer.class, String.class, Float.class, String.class }); Employee employee = (Employee)constructor.newInstance(new Object[]{ 100, "李磊", 300f, "研发部" }); System.out.println(employee); //选择特定方法 Method updateSalary = employeeClass.getMethod("updateSalary", new Class[]{Float.class }); //执行方法 Employee employee1 = (Employee)updateSalary.invoke(employee,new Object[]{1000f}); System.out.println(employee1); /** * 执行结果 * Employee类已经被加载到jvm,并初始化 * Employee带参方法被执行... * Employee{eno=100, ename='李磊', salary=300.0, dname='研发部'} * 调整薪资为1300.0元 * Employee{eno=100, ename='李磊', salary=1300.0, dname='研发部'} */ } }
package reflect; import reflect.entity.Employee; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; /** * 成员变量 **/ public class FieldSample { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException { Class employeeClass=Class.forName("reflect.entity.Employee"); Constructor constructor = employeeClass.getConstructor(new Class[]{ Integer.class, String.class, Float.class, String.class }); Employee employee = (Employee)constructor.newInstance(new Object[]{ 100, "李磊", 300f, "研发部" }); System.out.println(employee); //public修饰 Field enameField = employeeClass.getField("ename"); enameField.set(employee,"李雷"); String ename = (String)enameField.get(employee); System.out.println("ename="+ename); } }
package reflect; import reflect.entity.Employee; import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** *非public成员变量 **/ public class getDeclaredSample { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { Class employeeClass=Class.forName("reflect.entity.Employee"); Constructor constructor = employeeClass.getConstructor(new Class[]{ Integer.class, String.class, Float.class, String.class }); Employee employee = (Employee)constructor.newInstance(new Object[]{ 100, "李磊", 300f, "研发部" }); Field[] fields = employeeClass.getDeclaredFields(); for (Field f:fields){ if(f.getModifiers()==1){ //public修饰 Object o = f.get(employee); System.out.println(f.getName()+":"+o); }else if(f.getModifiers()==2){ //private修饰 //拼装方法名getXxx String methodNames="get"+f.getName().substring(0,1).toUpperCase()+f.getName().substring(1); Method method = employeeClass.getMethod(methodNames); //这边不能强转 Object invoke = method.invoke(employee); System.out.println(f.getName()+":"+invoke); } } } }
关于Class类的getResource().getPath()方法
程序中配置文件如果放置在classes文件夹,那么我们就可以使用Class类的getResource().getPath()方法获取文件路径。
例如:
String path = DBUtil.class.getResource("/db.properties").getPath();
值得注意的文件是,如果发布程序的web容器(tomcat)安装的路径中存在空格
D:\Program Files\Apache Software Foundation\Tomcat 8.5
该方法将会得到URLEncode后的路径,类似这样。
D:/Program%20Files/Apache%20Software%20Foundation/Tomcat%208.5/
用上面这个绝对路径去获取所需要的文件的话,就会取不到文件。
比较稳妥的做法是将path进行一次URLDecode
path = URLDecoder.decode(path, chartset);
这篇关于反射的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-15JavaMailSender是什么,怎么使用?-icode9专业技术文章分享
- 2024-11-15JWT 用户校验学习:从入门到实践
- 2024-11-15Nest学习:新手入门全面指南
- 2024-11-15RestfulAPI学习:新手入门指南
- 2024-11-15Server Component学习:入门教程与实践指南
- 2024-11-15动态路由入门:新手必读指南
- 2024-11-15JWT 用户校验入门:轻松掌握JWT认证基础
- 2024-11-15Nest后端开发入门指南
- 2024-11-15Nest后端开发入门教程
- 2024-11-15RestfulAPI入门:新手快速上手指南