Java教程

Java反射机制

本文主要是介绍Java反射机制,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

一、什么是反射?

        反射:指程序可以访问、检测和修改它本身状态或行为的一种能力。

        Java反射机制的核心是在程序运行时动态加载类,或获取类对象中的类信息,从而操作类或对象的属性和方法。

二、反射的优缺点

  • 优点

     1、在运行期间,动态加载额外的资源;

     2、在运行期间,动态访问和修改类信息,及其相关的类行为;

     3、动态创建实例对象,与程序显式创建解耦,提高程序的可扩展性;

  • 缺点

          1、反射会消耗一定的系统资源,由于JVM动态加载类信息造成的;

          2、反射改变类行为时,可以忽略权限检查,因此可能会破坏封装性而导致安全问题;

三、Java程序执行的三阶段 

  •  source源码阶段:*.java 被编译成*.class 字节码文件;

  • class类对象阶段:  *.class字节码文件被类加载器加载进内存(准备->验证->解析);

  • runtime运行时阶段:根据类定义信息,创建实例对象;

四、获取Class对象的方式 

  • source源代码阶段:Class.forName("全类名"),返回值为类对象;

  • class类对象阶段:类名.class,通过类名的属性class获取;

  • runtime运行时阶段:对象.getClass(),getClass()方法定义在Object类中;

        额外扩展: method.setAccessible(true); //暴力反射

@Test
public void reflect1() throws ClassNotFoundException {
    //方式一:Class.forName("全类名");
    Class cls1 = Class.forName("com.test.domain.Person");   //Person自定义实体类
    System.out.println("cls1 = " + cls1);


    //方式二:类名.class
    Class cls2 = Person.class;
    System.out.println("cls2 = " + cls2);


    //方式三:对象.getClass();
    Person person = new Person();        
    Class cls3 = person.getClass();
    System.out.println("cls3 = " + cls3);


    // == 比较三个对象
    System.out.println("cls1 == cls2 : " + (cls1 == cls2));    //true
    System.out.println("cls1 == cls3 : " + (cls1 == cls3));    //true
    //结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,无论通过哪一种方式获取的Class对象都是同一个。
}

 执行结果如下所示:

五、反射机制常用的类 

  • Java.lang.Class;

  • Java.lang.reflect.Constructor;

  • Java.lang.reflect.Field;

  • Java.lang.reflect.Method;

  • Java.lang.reflect.Modifier;

六、操作Class对象的方式

 1)获取成员变量们

Field[] getFields();//获取所有public修饰的成员变量
Field getField(String name); //获取指定名称的 public修饰的成员变量
Field[] getDeclaredFields(); //获取所有的成员变量,不考虑修饰符
Field getDeclaredField(String name);

  2)获取构造方法们

Constructor<?>[] getConstructors();  
Constructor<T> getConstructor(类<?>... parameterTypes);  
Constructor<?>[] getDeclaredConstructors();
Constructor<T> getDeclaredConstructor(类<?>... parameterTypes); 

3)获取成员方法们

Method[] getMethods();
Method getMethod(String name, 类<?>... parameterTypes); 
Method[] getDeclaredMethods();
Method getDeclaredMethod(String name, 类<?>... parameterTypes);

 4)获取全类名

String getName();

七、案例 

(1)Person类

package com.test.domain;

public class Person {
    //无参方法
    public void eat(){
        System.out.println("eat...");
    }
}

(2)编写配置文件( pro.properties)

className = com.test.domain.Person
methodName = eat

(3)编写测试方法 

package com.test.junit;

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

 (4)运行结果

 

这篇关于Java反射机制的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!