Java—反射

Posted 超霸霸

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java—反射相关的知识,希望对你有一定的参考价值。

反射

一、概念

  • 框架:半成品软件,可以在框架的基础上进行软件开发,简化编程
  • 反射:将类的各个组成部分封装为其他对象,这就是反射机制
  • 好处:
    1. 可以在程序运行过程中操作这些对象
    2. 可以解耦,提供程序的可扩展性

二、class对象

  • 获取class对象的方式

    1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象

      • 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
    2. 类名.class:通过类名的属性class获取

      • 多用于参数的传递
    3. 对象.getclass():getclass()方法在object类中定义者

      • 多用于对象的获取字节码的方式
    4. 同一个字节码文件(*.class)在一次程序运行过程中,只会加载一次,不论通过哪一种方式获取的class对象都是同一个

    //1.Class.forName("全类名")
    Class cls1=Class.forName("cn.chao.web.domain.person");
    System.out.println(cls1);
    
    //2.类名.class
    Class cls2= person.class;
    System.out.println(cls2);
    
    //3.对象.getClass()
    person p=new person();
    Class cls3=p.getClass();
    System.out.println(cls3);
    
  • class对象功能

    1. 获取成员变量

      • Field[] getFields():获取所有public修饰的成员变量
      • Field[] getField(String name):获取指定名称的public修饰的成员变量
      • Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符
      • Field[] getDeclaredField(String name)
      • 操作:
        1. 设置值:void set(Object obj, Object value)
        2. 获取值:get(Object obj)
        3. 忽略访问权限修饰符的安全检查:setAccessible(true)暴力反射
      //获取所有public成员变量
      Class personClass= Person.class;
      Field[] fields=personClass.getFields();
      for(Field field:fields)
          System.out.println(field);
      
      System.out.println("---------");
      Field a=personClass.getField("a");
      //获取public成员变量a的值
      Person p=new Person();
      Object value=a.get(p);
      System.out.println(value);
      //设置a的值
      a.set(p,2);
      System.out.println(p);
      System.out.println("---------");
      //获取所有成员变量
      Field[] declaredfields=personClass.getDeclaredFields();
      for(Field field:declaredfields)
          System.out.println(field);
      
      System.out.println("---------");
      //获取私有成员变量id的值
      Field id=personClass.getDeclaredField("id");
      //忽略访问权限修饰符的安全检查
      id.setAccessible(true);//暴力反射
      Object value2=id.get(p);
      System.out.println(value2);
      
    2. 获取构造方法

      • Constructor<?>[] getConstructors()
      • Constructor<T>[] getConstructor(类<?>... parameterTypes)
      • Constructor<?>[] getDeclaredConstructors()
      • Constructor<T>[] getDeclaredConstructor(类<?>... parameterTypes)
      • 如果使用空参构造方法创建对象,操作可以简化:Class对象的newInstance方法
      • 执行方法:Object invoke(Object obj, Object... args)
      • 获取方法名:String getName()
      Class personClass = Person.class;
      
      //获取指定构造器
      Constructor constructor=personClass.getConstructor(String.class,String.class);
      System.out.println(constructor);
      //创建对象
      Object person=constructor.newInstance("chao","asd");
      System.out.println(person);
      System.out.println("--------");
      
      //空参
      Constructor constructor1=personClass.getConstructor();
      System.out.println(constructor1);
      //1
      Object person1=constructor1.newInstance();
      System.out.println(person1);
      //2
      Object person2=personClass.newInstance();
      System.out.println(person2);
      System.out.println("--------");
      
    3. 获取成员方法

      • Method[] getMethods()
      • Method[] getMethod(String name,类<?>... parameterTypes)
      • Method[] getDeclaredMethods()
      • Method[] getDeclaredMethod(String name,类<?>... parameterTypes)
      Class personClass = Person.class;
      
      //获取指定名称的方法
      Method eat_method=personClass.getMethod("eat");
      Person p=new Person();
      //执行方法
      eat_method.invoke(p);
      System.out.println("-----------");
      
      //获取带参指定名称的方法
      Method eat_method2=personClass.getMethod("eat",String.class);
      //执行方法
      eat_method2.invoke(p,"shit");
      System.out.println("-----------");
      
      //获取所有public修饰的方法
      Method[] methods=personClass.getMethods();
      for(Method method:methods)
          String name=method.getName();
          System.out.println(name);
      
      System.out.println("-----------");
      
    4. 获取类名

      • String getName()

三、案例

  • 需求:写一个“框架”,不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象,并且执行其中任意方法

  • 实现:

    1. 配置文件
    2. 反射
  • 步骤:

    1. 将需要创建的对象的全类名和需求执行的方法定义在配置文件中
    2. 在程序中加载读取配置文件
    3. 使用反射技术来加载类文件进内存
    4. 创建方法
    5. 执行方法
  • pro.properties文件:

className=cn.chao.web.domain.Person
methodName=walk
  • reflectTest文件:
package cn.chao.web.reflect;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;

//在不改变代码的前提下,创建任意类的对象,执行任意方法
public class reflectTest 
    public static void main(String[] args) throws Exception 
        //1.加载配置文件
        //1.1创建Properties对象
        Properties pro=new Properties();
        //1.2加载配置文件,转换为一个集合
        //1.2.1获取class目录下的配置文件
        ClassLoader classLoader=reflectTest.class.getClassLoader();
        InputStream is = classLoader.getResourceAsStream("pro.properties");
        pro.load(is);

        //2.获取配置文件中定义的数据
        String className=pro.getProperty("className");
        String methodName=pro.getProperty("methodName");

        //3.加载该类进内存
        Class cls=Class.forName(className);

        //4.创建对象
        Object obj=cls.newInstance();

        //5.获取方法对象
        Method method=cls.getMethod(methodName);

        //6.执行方法
        method.invoke(obj);
    

以上是关于Java—反射的主要内容,如果未能解决你的问题,请参考以下文章

JAVA反射Field

反射机制在java中如何做呀?

如何利用java的反射机制动态创建对象

说说对java反射的理解,使用反射如何获取一个类的所有方法,使用反射需要注意哪些问题?

请问java中的反射机制与用法

Java反射机制