反射知识的理解

2018-07-18  本文已影响6人  须臾之北

反射

本文参考自:https://blog.csdn.net/sinat_38259539/article/details/71799078#commentBox

一、反射概述

  1. 能够分析类能力的程序称为反射
  1. JAVA反射机制是在运行状态中:
    • 对于任意一个类,都能够知道这个类的所有属性和方法;
* 对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
* 要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
  1. 反射就是把java类中的各种成分映射成一个个的Java对象

    • 例如:一个类有:成员变量、方法、构造方法、包等等信息
    • 利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。
    • (其实:一个类中这些成员方法、构造方法、在加入类中都有一个类来描述)
    • 如图是类的正常加载过程:反射的原理在与class对象。
    • 熟悉一下加载的时候:Class对象的由来是将class文件读入内存,并为之创建一个Class对象。
    image
  2. 若要学习反射,必须了解Class类

二、Class类

* 也就是jvm中有N多的实例每个类都有该Class对象。(包括基本数据类型)

返回Class类型实例

  1. Object类中的getClass()方法

     Employee e;
     Class c1 = e.getClass();  //获取到Employee类
    
     /*
         此时还有一个常用的方法getName()
     */
     System.out.println(c1.getName());
    
  2. T.class(),此时T为任意的java类型

     Class c1 = Random.class;
     Class c2 = int.class;
     Class c3 = Double[].class;
    
  3. 通过Class类中的static方法forName()

     String className = "java.util.Random";
     
     try{
         Class c1 = Class.forName(className);
         System.out.println(c1.getName());
     }
     catch(ClassNotFoundException e){
         e.getMessage();     
     }
    
     /*
         1. forName()方法抛出ClassNotFoundException
         2. className必须是类名或者接口
     */
    

通过反射获取构造方法并使用

自定义Employee类
package reflect;

import java.time.LocalDate;

public class Employee{
    
    //data field
    private String name;
    private double salary;
    private LocalDate hireDay;
    
    //constructor
    public Employee() {
        System.out.println("c1.getConstructor().newInstance()被执行,调用了无参构造器");        
    }


    public Employee(String name,double salary,int year,int month,int day){
        this.name = name;
        this.salary = salary;
        this.hireDay = LocalDate.of(year,month,day);
        System.out.println("getConstructor(Class,Class....).newInstance(para,para....)被执行");        
    }

    //method
    public String getName(){
        return name;    
    }
    
    public double getSalary(){
        return salary;  
    }
    
    public LocalDate gethireDay(){
        return hireDay;
    }
    
    public void raiseSalary(double byPercent){
        salary += salary * byPercent/100;
    }
    
    public String toString() {
        return "name : " + name + "salary : " + salary + " hireDay : " + hireDay;
    }
}
获取构造方法并使用
获取构造方法并使用例子程序
public class TestConstructors {
    
    public static void main(String[] args) {
        Class c1 = null;
        
        //获取Class对象
        try {
             c1 = Class.forName("d_1reflect.Employee");
        }catch(ClassNotFoundException e) {
            e.printStackTrace();
        }
        
        //获取构造方法
        System.out.println("========获取所有构造方法========");
        Constructor<Employee>[] constructors = c1.getDeclaredConstructors();        
        
        //输出构造方法        
        for(Constructor cons : constructors) {
            System.out.println(cons);           
        }
        
        System.out.println();
        
        //使用构造方法中的无参构造器
        System.out.println("======使用构造方法中的无参构造器======");
        
        try {
            Constructor<Employee> nonParaCons = c1.getConstructor();
            System.out.println(nonParaCons.newInstance());
        } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
                | NoSuchMethodException | SecurityException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        
        System.out.println();
                
        //使用构造方法中的含参构造器
        System.out.println("======使用构造方法中的含参构造器======");
        try {
            Constructor<Employee> paraCons = c1.getConstructor(String.class,double.class,int.class,int.class,int.class);
            System.out.println(paraCons.newInstance("调用有参构造器",600,2018,7,18));
        } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
                | NoSuchMethodException | SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }       
    }   
}

通过反射获取普通方法并使用

通过反射获取普通方法并使用例子程序

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestMethod {
    public static void main(String[] args) {
        //获取Class对象
        Class c1 = null;
        
        try {
            c1 = Class.forName("d_1reflect.Employee");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        
        //获取所有普通方法并输出
        Method[] method = c1.getDeclaredMethods();
        
        System.out.println("===========获取所有普通方法===========");
        for(Method m : method) {
            System.out.println(m);
        }
        
        ///获取单个普通方法
        System.out.println("===========获取单个普通方法===========");
        Method m = null;
        try {
             m = c1.getDeclaredMethod("getName");
            System.out.println(m);
        } catch (NoSuchMethodException | SecurityException e) {
            e.printStackTrace();
        }   
        
        //使用普通方法
        System.out.println("===========使用普通方法===========");
        Employee emp;
        try {
            emp = (Employee)c1.getDeclaredConstructor(String.class,double.class,int.class,int.class,int.class).newInstance("hahaha",200,2018,7,18);
            System.out.println("调用Method类中invoke(Object,para)方法后 : " + m.invoke(emp, null));
        } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
                | NoSuchMethodException | SecurityException e) {
            e.printStackTrace();
        }   
    }
}

/*
 * 在JDK1.8中输出结果为:
 * -----------------------------------------------------------------------
 * ===========获取所有普通方法===========
    public java.lang.String d_1reflect.Employee.toString()
    public java.lang.String d_1reflect.Employee.getName()
    public void d_1reflect.Employee.setName(java.lang.String)
    public double d_1reflect.Employee.getSalary()
    public java.time.LocalDate d_1reflect.Employee.gethireDay()
    public void d_1reflect.Employee.raiseSalary(double)
    public java.lang.String d_1reflect.Employee.testMethod(java.lang.String)
    ===========获取单个普通方法===========
    public java.lang.String d_1reflect.Employee.getName()
    ===========使用普通方法===========
    调用Method类中invoke(Object,para)方法后 : hahaha
    -----------------------------------------------------------------------
 * */

通过反射获取成员变量

通过反射获取成员变量例子程序

public class TestField {
    public static void main(String[] args) {
        
        Class c1 = null;
        //获取Class对象
        try {
            c1 = Class.forName("d_1reflect.Employee");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        //获取成员变量信息
        Field[] fields = c1.getDeclaredFields();
        
        System.out.println("=========获取成员变量信息=========");
        for(Field field : fields) {
            System.out.println(field);
        }
        
        //获取单个成员变量信息
        System.out.println("=========获取单个成员信息=========");
        Field f = null;
        try {
            f = c1.getDeclaredField("name");
            System.out.println(f);
        } catch (NoSuchFieldException | SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        //使用成员变量
        Employee emp;
        try {
            emp = (Employee)c1.getConstructor().newInstance();
            f.setAccessible(true);//暴力反射,解除私有设定
            f.set(emp, "xixixi");
            System.out.println("使用了set方法修改成员变量 name: " + emp.getName());
        } catch (IllegalArgumentException | IllegalAccessException | InstantiationException | InvocationTargetException
                | NoSuchMethodException | SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }       
    }
}
/*
 * 在JDK1.8中输出结果为:
 * ---------------------------------------------------------
 * =========获取成员变量信息=========
    private java.lang.String d_1reflect.Employee.name
    private double d_1reflect.Employee.salary
    private java.time.LocalDate d_1reflect.Employee.hireDay
    =========获取单个成员信息=========
    private java.lang.String d_1reflect.Employee.name
    c1.getConstructor().newInstance()被执行,调用了无参构造器
    使用了set方法修改成员变量 name: xixixi
    ---------------------------------------------------------
 * */

反射与配置文件结合使用

上一篇 下一篇

猜你喜欢

热点阅读