Java反射机制

基本概念

在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?答案是肯定的。这种动态获取类的信息以及动态调用对象的方法的功能来自于Java语言的反射(Reflection)机制。

Java反射机制主要提供了以下功能:

  • 在运行时判断任意一个对象所属的类。
  • 在运行时构造任意一个类的对象。
  • 在运行时判断任意一个类所具有的成员变量和方法。
  • 在运行时调用任意一个对象的方法。

Reflection是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息。包括其modifiers(诸如public、static等)、 superclass(例如Object)、实现了的 interfaces (例如Serializable)、也包括其fields和methods的所有信息,并可于运行时改变fields内容或调用methods。

动态语言

动态语言的定义“程序运行时,允许改变程序结构或者变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。尽管在这样的定义与分类下Java不是动态语言,它却有着一个非常突出的动态相关机制:Reflection。这个字的意思是:反射、映像、倒影,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。这种“看透”class的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。

Java Reflection API简介

  
在JDK中,主要由以下类来实现Java反射机制,这些类(除了第一个)都位于java.lang.reflect包中

  • Class类:代表一个类,位于java.lang包下。
  • Field类:代表类的成员变量(成员变量也称为类的属性)。
  • Method类:代表类的方法。
  • Constructor类:代表类的构造方法。
  • Array类:提供了动态创建数组,以及访问数组的元素的静态方法。

反射

  • 1.Class 代表类的类,用来表示一个类

    • 1.Class.forName(“类的包名+类名”);
    • 2.对象名.getClass()
    • 2.类名.class
    • 基本数据类型,String,void,数组,引用类型都存在类类型Class
    • 方法
      • 1.newInstance(); 创建实例对象
      • 2.getName(); 获取类的名字,带包名的
      • 3.getSimpleName(); 获取不带包名的类名
      • 4.getMethod(方法名,方法参数的字节码); 获取指定公有的方法 Method method = clazz.getMethod(“eat”, String.class,Integer.class) 没有参数列表的设置为null
      • 5.method.invoke(clazz.newInstance(), “狗粮”,10) 调用一些私有方法需要先打开权限 method.setAccessible(true); 注意静态方法不需要实例 method.invoke(null, “狗粮”,10)
      • 6.getDeclaredMethod(); 获取所有的指定的方法
      • 7.getMethods(); 获取所有公有的方法(包含父类的公有的方法) Method[] methods = clazz.getMethods();
      • 8.getDelcaredMethods(); 获取类上面所有的方法(包含非公有的方法 当前类的方法)
      • 9.getFields(); 获取所有公有的成员变量 Field[] fields = clazz.getFields();
      • 10.getField(“成员变量的名称”); 通过成员变量的名字获取公有的成员变量
      • 11.getDeclaredField(“成员变量的名称”); 通过成员变量的名字获取成员变量
      • 12.getDeclaredFields(); 获取所有的成员变量 Field[] fields = clazz.getDeclaredFields();
      • 13.getConstructor(“”,”“,”“);传入类型字节码
      • 14.getConstructors();
      • 15.getDeclaredConstructor(parameterTypes);传入类型字节码
        加载类(静态加载”的类在编译的时候就要提供,而动态加载的类在源程序编译时可以缺席)
    • 1.静态加载(通过new的方式获取对象,都属于静态加载)
    • 2.动态加载

    为了区别动态加载和静态加载区别我们首先来看一个列子,

    首先定义三个类分别为Word、PPT、Excel:

    public class Word {
        public Word() {
            System.out.println("wrod运行了");
        }
    }

    public class PPT {
        public PPT() {
            System.out.println("PPT运行了");
        }
    }

    public class Excel {
        public Excel() {
            System.out.println("excel运行了");
        }
    }

静态调用方法:

public class StaticLoad {
        public static void main(String[] args) {
            User user=new User();
            user.use("PPT");
        }
    }

    public class User {
        public void use(String officeName){
            if("word".equals(officeName)){
                new Word();
            }else if("PPT".equals(officeName)){
                new PPT();
            }else if("excel".equals(officeName)){
                new Excel();
            }

        }
    }

动态调用方法:

 public class DynamicLoad {
     public static void main(String[] args) {
        ClassBoss boss=new ClassBoss();
        boss.work("PPT");
     }
   }

   public class ClassBoss {
    public void work(String officeName){
        try {
            Class clazz = Class.forName("cn.test."+officeName);
            clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
     }
   }

从上面可以看出两种加载方式虽然都能正常运行,但是当我们要增加一个Email功能时候,很明显静态加载方式的代码需要大改,而动态加载方式的代码则不需要改动太大,但是为什么我们在开发中不直接使用动态加载的方式尼?因为这种方式相比静态加载方式耗时,效率要低很多。

  • 2.Constructor 构造方法
    • 1.getName(); 获取构造方法的名字
    • 2.getParameterTypes(); 获取所有参数的类类型
  • 3.Method 成员方法
    • 1.method.getReturnType(); 获取返回值的类类型
    • 2.method.getName(); 获取方法的名字
    • 3.method.getParameterTypes(); 获取所有参数的类类型
  • 4.Field 成员变量
    • 1.getName(); 获取成员变量的名称
    • 2.getType(); 返回成员变量的类类型 Class
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值