Java反射

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();

        }
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值