1.反射及其作用
- 反射(Reflect)是在运行时动态访问类与对象的技术
- 反射是JDK1.2版本后的高级特性,隶属于java.lang.reflect
- 大多数Java框架都基于反射实现参数配置、动态注入等特性
例:
package com.imooc.reflect;
public interface MathOperation {
float operate(int a, int b);
}
package com.imooc.reflect;
public class Addition implements MathOperation{
@Override
public float operate(int a, int b) {
//加法
return a+b;
}
}
package com.imooc.reflect;
public class Subtraction implements MathOperation{
@Override
public float operate(int a, int b) {
//减法法
return a-b;
}
}
package com.imooc.reflect;
import java.util.Scanner;
import org.junit.Test;
public class ReflectDemo {
public static void main(String[] args) {
test2();
}
//不使用反射
public static void test1 (){
//获取输入
Scanner scanner = new Scanner(System.in);
System.out.println("请输入计算类名:");
String op = scanner.next();
System.out.println("请输入a");
int a = scanner.nextInt();
System.out.println("请输入b");
int b = scanner.nextInt();
MathOperation mathOperation = null;
if(op.equals("Addition")){
mathOperation = new Addition();
}else if(op.equals("Subtraction")){
mathOperation = new Subtraction();
}else {
System.out.println("无效的计算类");
}
float result = 0;
if(mathOperation!=null){
result = mathOperation.operate(a,b);
}
System.out.println(result);
}
//使用反射创建对象更加灵活
public static void test2 (){
//获取输入
Scanner scanner = new Scanner(System.in);
System.out.println("请输入计算类名:");
String op = scanner.next();
System.out.println("请输入a");
int a = scanner.nextInt();
System.out.println("请输入b");
int b = scanner.nextInt();
MathOperation mathOperation;
try {
//使用反射在运行时根据需要选择加载的类
mathOperation = (MathOperation)Class.forName("com.imooc.reflect." + op).newInstance();
}catch (Exception e){
throw new RuntimeException(e);
}
float result = mathOperation.operate(a,b);
System.out.println(result);
}
}
使用反射在运行时根据需要选择加载的类,使用起来更灵活。
2.反射的核心类
- Class类
- Constructor构造方法类
- Method方法类
- Field成员变量类
3.Class类及对象实例化
定义:
- Class类是JVM中代表"类和接口"的类
- Class对象具体包含了某个特定类的结构信息
- 通过Class对象科获取对应类的构造方法、方法、成员变量
Class核心方法:
- Class.forName():静态方法,用于获取指定Class对象
- classObj.newInstance():通过默认构造方法创建新的对象
- classObj.getConstructor():获得指定的public修饰构造方法Constructor对象
- classObj.getMthod():获得指定的public修饰方法Method对象
- classObj.getField():获得指定的public修饰成员变量Field对象
例:
package com.imooc.reflect;
/**
* 员工实体类
*/
public class Employee {
static {
System.out.println("Employee已被加载到jvm,并已被初始化");
}
private Integer eno;
private String ename;
private double salary;
private String dname;
public Employee(){
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 double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
}
package com.imooc.reflect;
public class ClassSample {
public static void main(String[] args) {
try {
//Class.forName() 方法将指定的类加载到jvm,并返回对应的Class对象
Class employeeClass = Class.forName("com.imooc.reflect.Employee");
System.out.println("Employee已被加载到jvm");
//newInstance通过默认的构造方法创建新的对象
Employee emp = (Employee)employeeClass.newInstance();//newInstance返回的是Object,需要强转
System.out.println(emp);
}catch (Exception e) {
e.printStackTrace();
}
}
}
3.Constructor构造方法类
定义:
- Constructor类是对Java类中的构造方法的抽象
- Constructor对象包含了具体类的某个具体构造方法的声明
- 通过Constructor对象调用带参构造方法创建对象
Constructor类核心方法
- classObj.getConstructor():获得指定的public修饰构造方法
- constructorObj.newInstance():通过对应的构造方法创建新的对象
例:
package com.imooc.reflect;
/**
* 员工实体类
*/
public class Employee {
static {
System.out.println("Employee已被加载到jvm,并已被初始化");
}
private Integer eno;
private 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 double 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 + '\'' +
'}';
}
}
package com.imooc.reflect;
import java.lang.reflect.Constructor;
/**
* 利用带参构造方法创建对象
*/
public class ConstructorSample {
public static void main(String[] args) {
try {
//Class.forName() 方法将指定的类加载到jvm,并返回对应的Class对象
Class employeeClass = Class.forName("com.imooc.reflect.Employee");
//得到指定格式的构造方法对象
Constructor constructor = employeeClass.getConstructor(new Class[]{
Integer.class, String.class, Float.class, String.class
});
Employee employee = (Employee)constructor.newInstance(new Object[]{
100, "张三", 3000f, "研发部"
});
System.out.println(employee);
}catch (Exception e) {
e.printStackTrace();
}
}
}
4.Method方法类
定义:
- Method对象指代某个类中方法的描述
- Method对象使用classObj.getMethod()方法获取
- 通过Method对象调用指定对象的对应方法
Method类核心方法:
- classObj.getMethod():获取指定public修饰的方法对象
- methodObj.invoke():调用指定对象的对应方法
例:
package com.imooc.reflect;
/**
* 员工实体类
*/
public class Employee {
static {
System.out.println("Employee已被加载到jvm,并已被初始化");
}
private Integer eno;
private 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 double 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 java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class MethodSample {
public static void main(String[] args) {
try {
//Class.forName() 方法将指定的类加载到jvm,并返回对应的Class对象
Class employeeClass = Class.forName("com.imooc.reflect.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 updateSalary = employeeClass.getMethod("updateSalary", new Class[]{
Float.class
});
//执行方法
Employee employee2 = (Employee)updateSalary.invoke(employee, new Object[]{
1000f
});
System.out.println(employee2);
}catch (Exception e) {
e.printStackTrace();
}
}
}
4.Field成员变量类
定义:
- Field对应某个具体类中的成员变量的声明
- Field对象使用classObj.getField()方法获取
- 通过Field对象可为某对象成员变量赋值/取值
Field类核心方法:
- classObj.getField():获取指定public修饰的成员变量对象
- fieldObj.set():为某对象指定成员变量赋值
- fieldObj.get():获取某对象指定成员变量数值
例:
package com.imooc.reflect;
/**
* 员工实体类
*/
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 double getSalary() {
return salary;
}
public void setSalary(Float salary) {
this.salary = salary;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
}
package com.imooc.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class FieldSample {
public static void main(String[] args) {
try {
//Class.forName() 方法将指定的类加载到jvm,并返回对应的Class对象
Class employeeClass = Class.forName("com.imooc.reflect.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 enameField = employeeClass.getField("ename");
enameField.set(employee,"李四");
String ename = (String)enameField.get(employee);
System.out.println(ename);
}catch (Exception e) {
e.printStackTrace();
}
}
}
4.getDeclared系列方法
例:
package com.imooc.reflect;
/**
* 员工实体类
*/
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 double getSalary() {
return salary;
}
public void setSalary(Float salary) {
this.salary = salary;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
}
package com.imooc.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
public class getDeclaredSample {
public static void main(String[] args) {
try {
//Class.forName() 方法将指定的类加载到jvm,并返回对应的Class对象
Class employeeClass = Class.forName("com.imooc.reflect.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[] declaredFields = employeeClass.getDeclaredFields();
for (Field declaredField : declaredFields) {
//判断字段的修饰符
if (declaredField.getModifiers()==1) {//public修饰
//获取属性名
System.out.println(declaredField.getName());
//获取属性值
System.out.println(declaredField.get(employee));
}else if (declaredField.getModifiers()==2) {//private修饰
//setAccessible(true)允许我们请求JVM忽略Java的访问控制检查。
// 当我们将此方法的参数设置为 true 时
// 我们就可以访问类的私有成员
declaredField.setAccessible(true);
//获取私有属性值
System.out.println(declaredField.get(employee));
}
}
}catch (Exception e) {
e.printStackTrace();
}
}
}