首页 > 编程语言 > 详细

Java反射机制

时间:2020-03-11 17:00:38      阅读:77      评论:0      收藏:0      [点我收藏+]

一、什么是反射机制

  在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。简单来说,就是Java对每一个类和类中的所有成员都进行了封装,这样每个类都有一个与之对应的Class对象,通过这个对象可以直接访问类中的所有成员。

二、反射机制的作用

① 在运行时判断任意一个对象所属的类

② 在运行时构造任意一个类的对象

③ 在运行时判断任意一个类所具有的成员变量和方法

④ 在运行时调用任意一个对象的方法;生成动态代理

三. 反射机制的优点与缺点

首先要搞清楚为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念。 

静态编译:在编译时确定类型,绑定对象,即通过。

动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。 

● 优点:可以实现动态创建对象和编译,体现出很大的灵活性(特别是在J2EE的开发中它的灵活性就表现的十分明显)。通过反射机制我们可以获得类的各种内容,进行了反编译。对于JAVA这种先编译再运行的语言来说,反射机制可以使代码更加灵活,更加容易实现面向对象。

  比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个程序编译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功能。 

缺点:对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它 满足我们的要求。这类操作总是慢于只直接执行相同的操作。

四、Java类反射中所必须的类

除了Class类之外,基本都在java.lang.reflect包中。它们分别是:Field、Constructor、Method、Class、Object,下面我将对这些类做一个简单的说明。

● Class类:类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。

● Constructor类:提供关于类的单个构造方法的信息以及对它的访问权限。这个类和Field类不同,Field类封装了反射类的属性,而Constructor类则封装了反射类的构造方法。

● Field类:提供有关类或接口的属性的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)属性或实例属性,简单的理解可以把它看成一个封装反射类的属性的类。

● Method类:提供关于类或接口上单独某个方法的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。 这个类不难理解,它是用来封装反射类方法的一个类。
● Object类:每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。

五、获取字节码方式

在类加载的时候,jvm会创建一个class对象;class对象是反射机制中常用的,用来获取class对象的字节码文件

在 Java 中可以通过三种方法获取类的字节码 (Class) 对象:

// 获取字节码对象的三种方式
Class c = 对象.getClass();已经创建对象一般不需要进行反射
Class c = 类名.class;需要导入类的包,依赖性太强
Class c = Class.forName("package.className");使用字符串获取(含包名),一般开发中选择这种★

// 使用Class对象创建该对象实例:
Object obj = c.newInstance();

六、获取类的构造函数

● Constructor [] getConstructors();获取public权限的所有构造器

● Constructor getConstructor(Class<?>...params);根据指定参数获得public权限的构造器

● Constructor [] getDeclaredConstructors();获取public权限的所有构造器

● Constructor getDeclaredConstructor(Class<?>...params);根据指定参数获得public权限和非public权限的构造器 

Class c = Class.forName("bean.Person");
// 1、获取这个带有参数的构造器
Constructor<?> con = c.getConstructor(String.class,int.class);
// 2、使用构造器来创建:
Object obj = con.newInsatnce("LiSi",20);

七、获取类的字段

● Field [] getFields();获得类中所以public权限的方法;

● Field getField(String name);根据变量名得到相应的public权限的变量;

● Field [] getDeclaredFields();获得类中所有的public权限和非public的权限方法 ;

● Field getDeclaredField(String name);根据方法名获得public权限和非public权限的变量;

package reflect;
import java.lang.reflect.Field;

public class getFieldDemo {
    public static void main(String[] args) throws Exception {
        String className = "bean.Person";
        Class<?> c = Class.forName(className);
        
        // 获取私有字段
        Field nameField = c.getDeclaredField("name");
        Field ageField = c.getDeclaredField("age");
         
        // 使用字段(使用之前我们需要一个该类对象)
        Object obj = c.newInstance();
         
        // 使用set()方法设置字段值
        nameField.setAccessible(true);
        ageField.setAccessible(true);// 暴力访问
        nameField.set(obj, "张三");
        ageField.set(obj,20);
         
        // 打印查看效果
        System.out.println("获取到的字段:");
        System.out.println("name:"+nameField);
        System.out.println("age:"+ageField);
        System.out.println("字段设置的值:name="+nameField.get(obj)+",age="+ageField.get(obj));
    }
}

八、获取类的方法

● Method [] getMethod();获取所有的public方法,包括继承的

● Method getMethods(String name,Class [] params);根据方法名和参数获取方法;

● Method [] getDeclaredMethod();获取所有public权限和非public权限方法,不包含继承的

● Method getDeclaredMethods(String name,Class [] params);根据方法名和参数类型,获取public权限和非public权限的方法

package reflect;
import java.lang.reflect.Method;

public class getMethodDemo {
    public static void main(String[] args) throws Exception {
        String className = "bean.Person";
        Class<?> c = Class.forName(className);
         
        //获取公共方法:
        Method[] pubMethods = c.getMethods();
         
        //获取私有方法:
        Method[] priMethods = c.getDeclaredMethods();
         
         
        //获取单个方法:按方法名和参数获取
         
        //获取单个の静态方法:function1
        Method staMethod = c.getMethod("function1",null);
        //获取单个の无参数方法:function2
        Method nullMethod = c.getMethod("function2",null);
        //获取单个の有参数方法:function3
        Method moreMethod = c.getMethod("function3",String.class,int.class);
        //获取单个の私有方法:function4
        Method priMethod = c.getDeclaredMethod("function4",null);
        
        //打印查看效果
        System.out.println("[Person类的公共方法及父类方法:]");
        for(Method m:pubMethods){
            System.out.println(m);
        }
        System.out.println("[Person类的私有方法:]");
        for(Method m:priMethods){
            System.out.println(m);
        }
        System.out.println("[按方法名和参数类型获取的方法4个方法:]");
        System.out.println(staMethod);
        System.out.println(nullMethod);
        System.out.println(moreMethod);
        System.out.println(priMethod);    
    }
}

九、暴力访问setAccessible(boolean)

对私有字段的访问取消权限检查。暴力访问(私有的不建议使用) 

 

Java反射机制

原文:https://www.cnblogs.com/Dm920/p/12462685.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!