java反射机制(Reflection)(一)-- 概念及APIs介绍

前言
       Java 反射是Java语言的一个很重要的特征,它使得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反射机制API介绍
       在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中
       ①:Class类:代表一个类。【注:这个Class类进行继承了Object,比较特别】
       ②:Field 类:代表类的成员变量(成员变量也称为类的属性)。
       ③:Method类:代表类的方法。
       ④:Constructor 类:代表类的构造方法。
       ⑤:Array类:提供了动态创建数组,以及访问数组的元素的静态方法
 
<一>简单演示
要想使用反射机制,首先得获得需要处理的类或者对象的Class对象。我们有如下3中获取方式       
       ①:使用Class的静态方法forName():  例如:Class.forName("java.lang.Class");
       ②:使用XXX.Class语法:  例如:String.Class;
       ③:使用具体某个对象.getClass()方法: 例如String str="abc"; Class<?> tClass=str.getClass();
package reflection;
import java.lang.reflect.Method;
/**
 * @Description:使用反射来获取Class中的方法,包括私有的方法
 */
public class Reflection1 {
    public static void main(String[] args) {
        Class<?> classType = Class.class;
        Method[] methods = classType.getDeclaredMethods();
        //获取Class类的所有方法
        for(int i=0; i<methods.length; i++) {
            System.out.println(methods[i]);
        }
    }
}

 <二>Class类的常用方法,如下:
        ①: getName():获得类的完整名字。
        ②: getFields():获得类的public类型的属性。
        ③: getDeclaredFields():获得类的所有属性。
        ④: getMethods():获得类的public类型的方法。
        ⑤: getDeclaredMethods():获得类的所有方法。
        ⑥:getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字parameterTypes参数指定方法的参数类型。
        ⑦:getConstructors():获得类的public类型的构造方法。
        ⑧:getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes参数指定构造方法的参数类型。
        ⑨:newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
先看上面的⑧和⑨其中都能生成对象,但是因为构造函数有无参和有参构造函数两种,所以我们分两种情况考虑
 
情况一:无参构造方法
       <a>首先我们去获取Class对象,然后直接通过Class对象去调用newInstance()方法 

Class<?> classType = Reflection1.class;
Object object = classType.newInstance();

      <b>首先我们也是去获取Class对象,然后去去调用getConstructor()得到Constructor对象,接着直接调用newInstance()即可
Class<?> classType = Reflection2.class;
// Object reflection2 = classType.newInstance();
Constructor<?> constructor = classType.getConstructor(newClass[] {});
Object reflection2 = constructor.newInstance(newObject[]{});

情况二:有参构造方法 
Class<?> classType = Person.class; 
Constructor cons = classType.getConstructor(newClass[]{String.class,int.class});  
Object obj = cons.newInstance(newObject[]{“zhangsan”, 19});

<三>利用反射机制执行目标类的方法
package reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
 * @Description:使用反射访问类中的方法
 */
public class Reflection2 {
      
    public int sum(inta, int b) {
        return a + b ;
    }
  
    public static void main(String[] args) throws Exception {
        Class<?> classType = Reflection2.class;
        //下面两行代码等同 Object object = classType.newInstance();
        Constructor<?> constructor = classType.getConstructor(newClass[]{});
        Object reflection2 = constructor.newInstance(newObject[]{});
        //利用反射机制反射出类的方法
        Method method = classType.getMethod("sum",new Class[]{int.class,int.class});
        //动态执行method方法,invoke方法返回Object对象,如method返回int型,则invoke
        //会将int转换成Integer对象
        Object result = method.invoke(reflection2,new Object[]{6,10});
        System.out.println(result);
    }
}


   由于Java访问权限检查机制,私有变量和方法除了在本类中的其他地方都不能访问。可是我们利用反射机制可以绕过访问权限的检查。 具体的实现需要使用reflect包中的AccessibleObject类中的setAccessible方法。实际上类Constructor,Field,Method继承了AccessibleObject类。
package reflection;
class Test {
    private String addStr(String str) {
        return "This is the " + str;
    }
}
  
package reflection;
  
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
 * @Description:使用反射访问类中的私有方法
 */
public class Reflection3 {
    public static void main(String[] args) throws Exception {
        Test test =new Test();
        Class<?> classTest = test.getClass();
        Method addStrMethod = classTest.getDeclaredMethod("addStr",new Class[]{String.class});
        //设定是否对addStr方法的访问权限进行检查,true为不检查
        addStrMethod.setAccessible(true);
        Object result = addStrMethod.invoke(test,new Object[]{"反射执行私有方法"});
        System.out.println(result);
    }
}


下面我们来看看数组的反射使用,java.lang.Array 类提供了动态创建和访问数组元素的各静态方法。 
Class classType = Class.forName("java.lang.String");
Object array = Array.newInstance(String.class,3);
Array.set(array,1, "第一个元素");
System.out.println(Array.get(array,1));


 
 
 
 
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值