反射:运行时动态访问类与对象的技术
创建对象的时间 从编译时变成运行时
反射的作用:
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);
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/279241.html