文章目录
Java反射
一:概述
什么是反射Reflect?
-
反射(Reflect)是在运行时动态访问类和对象的技术;
-
反射是JDK1.2 以后的高级特性,隶属于 java.lang.reflect;
-
大多数java框架会基于反射实现参数配置,动态注入等特性;
二:反射的核心类
反射的核心类:
-
Class类
-
Constructor类
-
Method类
-
Field成员变量类
1.Class类
- 是JVM中代表“类和接口”的类
- Class对象具体包含了某个特定类的结构信息
- 通过Class对象可获取对应类的构造方法/方法/成员变量
测试代码:
//实体类
package com.imooc.reflect.entity;
/**
* 员工实体类
*/
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.ename + "调薪至" + this.salary + "元");
return this;
}
}
//测试类
package com.imooc.reflect;
import com.imooc.reflect.entity.Employee;
public class ClassSample {
public static void main(String[] args) {
try {
//Class.forName()方法将指定的类加载到jvm,并返回对应Class对象
Class employeeClass = Class.forName("com.imooc.reflect.entity.Employee");
System.out.println("Employee已被加载到jvm");
//newInstance通过默认构造方法创建新的对象,默认返回Object
Employee emp = (Employee)employeeClass.newInstance();
System.out.println(emp);
} catch (ClassNotFoundException e) {
//类名与类路径书写错误是抛出"类无法找到"异常
e.printStackTrace();
} catch (IllegalAccessException e) {
//非法访问异常,当在作用域外访问对象方法或成员变量时抛出
e.printStackTrace();
} catch (InstantiationException e) {
//对象无法被实例化,抛出"实例化异常"
e.printStackTrace();
}
}
}
2.Constructor类
Constructor构造方法类:
-
Constructor类是对Java类中的构造方法的抽象
-
Constructor对象包含了具体类的某个具体构造方法的声明
-
通过Constructor对象调用代参构造方法创建对象
注意:Class类对象的newInstance方法只能调用默认的无参构造方法实例化对象,而通过Constructor对象可以调用带参构造方法创建对象。要先通过Class类对象调用classObj.getConstructor()获取,参数为一个Class类对象数组,告诉编译器你想获取的构造方法中的参数数量和类型,核心方法:constructorObj.newInstance(),在得到Constructor对象后再执行实例化就需要传入参数了。
测试代码:
package com.imooc.reflect;
import com.imooc.reflect.entity.Employee;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* 利用带参构造方法创建对象
*/
public class ConstructorSample {
public static void main(String[] args) {
try {
Class employeeClass = Class.forName("com.imooc.reflect.entity.Employee");
/*
classObj.getConstructor()
获取指定public修饰的构造方法对象,需要传入一个类Class对象的数组,分别按前后顺序说明参数类型
*/
Constructor constructor = employeeClass.getConstructor(new Class[]{
Integer.class,String.class,Float.class,String.class
});
/*constructorObj.newInstance()
通过对应的构造方法创建对象(Object)
需要传入一个类Object对象的数组,分别按前后顺序说明参数类型*/
Employee employee = (Employee) constructor.newInstance(new Object[]{
100,"李磊",3000f,"研发部"
});
System.out.println(employee);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
//没有找到与之对应格式的方法
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
//当被调用的方法的内部抛出了异常而没有被捕获时
e.printStackTrace();
}
}
}
3.Method类
Method方法类:
-
Method对象指代某个类的方法的描述
-
Method对象使用classObj.getMethod()方法获取
-
最重要 :通过Method对象调用指定对象的对用方法
测试代码:
package com.imooc.reflect;
import com.imooc.reflect.entity.Employee;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 利用Method方法类调用
*/
public class MethodSample {
public static void main(String[] args) {
try {
Class employeeClass = Class.forName("com.imooc.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,"李磊",3000f,"研发部"
});
Method updateSalaryMethod = employeeClass.getMethod("updateSalary" , new Class[]{
Float.class
});
Employee employee1 = (Employee)updateSalaryMethod.invoke(employee,new Object[]{1000f});
System.out.println(employee1);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
4.Field成员变量类
Field成员变量类:
-
Field对应某个具体类中的成员变量的声明
-
Field通过classObj.getField()方法获取
-
通过Field对象可以为某对象的成员变量赋值或者取值
测试代码:
package com.imooc.reflect;
import com.imooc.reflect.entity.Employee;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class FieldSample {
public FieldSample() {
}
public static void main(String[] args) {
try {
Class employeeClass = Class.forName("com.imooc.reflect.entity.Employee");
Constructor constructor = employeeClass.getConstructor(Integer.class, String.class, Float.class, String.class);
Employee employee = (Employee)constructor.newInstance(100, "李磊", 3000.0F, "研发部");
Field enameField = employeeClass.getField("ename");
enameField.set(employee, "李雷");
String ename = (String)enameField.get(employee);
System.out.println("ename:" + ename);
} catch (ClassNotFoundException var6) {
var6.printStackTrace();
} catch (NoSuchMethodException var7) {
var7.printStackTrace();
} catch (InstantiationException var8) {
var8.printStackTrace();
} catch (IllegalAccessException var9) {
var9.printStackTrace();
} catch (InvocationTargetException var10) {
var10.printStackTrace();
} catch (NoSuchFieldException var11) {
var11.printStackTrace();
}
}
}
5.getDeclared系列方法说明
package com.imooc.reflect;
import com.imooc.reflect.entity.Employee;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 获取对象所有成员变量值
*/
public class getDeclaredSample {
public static void main(String[] args) {
try {
Class employeeClass = Class.forName("com.imooc.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, "李磊", 3000f, "研发部"
});
//获取当前类所有成员变量
Field[] fields = employeeClass.getDeclaredFields();
for(Field field : fields){
//System.out.println(field.getName());
/*filed.getModifiers() :
= = 1 时,该成员变量用public修饰
= = 2 时,该成员变量用private修饰
遇到用public修饰的成员变量可以直接获取,
如果是用private的修饰的成员变量,只能用get/set方法
*/
if(field.getModifiers() == 1){ //pubilc修饰
Object val = field.get(employee);
System.out.println(field.getName() + ":" + val);
}else if(field.getModifiers() == 2){ //private修饰
String methodName = "get" + field.getName().substring(0,1).toUpperCase()
+ field.getName().substring(1);
Method getMethod = employeeClass.getMethod(methodName);
Object ret = getMethod.invoke(employee);
System.out.println(field.getName() + ":" + ret);
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
三:反射的实际应用
定义一个接口和多个实现类,利用反射实现实例化不同的方法和类,只需修改配置文件