反射,是指一种能在运行时动态加载、分析类的能力。反射被广泛地用于那些需要在运行时检测或修改程序行为的程序中。这是一个相对高级的特性,使用反射技术应当具备相当的Java语言基础。我们可以通过反射机制让应用程序做一些几乎不可能做到的事情。

一. Class类

在java.lang包中有一个特殊的类,即Class类。JVM会为所有被加载的类创建一个对应的Class类的对象,这个对象保存了类的运行时信息。我们可以通过Class对象得到对应的类的一些特征,如类的名字,类有哪些属性,有哪些方法,类的超类是谁,甚至可以直接调用类中的方法。Class类是Java反射技术的基础。

三种获取Class实例的方法:

1. 通过Object.getClass()方法获取。

Object类是所有类的超类,在这个类中有一个getClass()方法,它可以返回这个类的Class对象。我们自定义一个简单的Point类来进行测试:

class Point
{
}
Point pt = new Point();

		Class c1 = pt.getClass(); //通过getClass()方法得到Class对象

2. 通过 类.class 方式获取

如果我们只知道一个类类型,没有此类的一个实例,那么就可以这样:

Class c2 = Point.class;

也就是说,每个类都有一个静态的class成员,可以直接用 类.class的方式得到。

3.通过Class.forName()方式获取

Class的静态方法forName()允许我们通过类的全名来得到Class对象。它需要一个字符串作为参数:

Class c3 = Class.forName("Point");

这时候需要捕获一个 ClassNotFoundException.

二、通过Class对象调用构造函数、成员方法

1. 调用无参数的构造函数创建对象

我们上面定义的Point类并没有定义构造方法,因此编译器会为我们提供一个无参数的默认构造方法。如果想要通过这个无参数的构造方法,则只需要调用Class的newInstance()方法即可得到Point类的一个实例:

Point pt2 = (Point)c1.newInstance(); //newInstance返回Object,因此需要强制转换

2. 调用有参数的构造函数创建对象

现在我们为Point类添加一个有参数的构造方法:

class Point
{
public Point(int i)
{
System.out.println(i);
}
}

如果我们想要调用这个带参数的构造方法,则必须先用 Class对象的getConstructors() 方法来得到一个表示(标识为public)构造方法的对象的数组。在java.lang.reflect包中有一个Constructor类,这个类就代表了一个构造方法。因此 getConstructors() 返回的是Constructor[] 数组。

Constructor[] cons = c1.getConstructors();

因为我们定义的Point类显然只有一个构造函数,所以我们直接使用cons[0]。

在Constructor类中,也有一个newInstance()方法,不过这个方法是带参数的,需要传递一个Object类型的数组。为什么呢?因为我们要调用的构造方法是带参数的,如果不告诉编译器这些参数应该怎么填,那就无法成功地调用该构造方法了。因此,这个Object数组顺理成章地应该就是要传递的参数了。

那么如何才能知道构造方法需要什么类型的参数,到底有几个参数呢?我们可以调用Constructor中的getParameterTypes()来获取所有参数的类型,该方法返回一个Class[]数组,数组中的每一个元素就代表了参数的类型。如本例中,Point的构造方法有一个int 类型的参数,那么返回的Class[]数组就只有一个元素,且这个元素会是一个Integer类的Class对象。当得知参数类型是Integer后,我们就可以为构造方法传递参数了。示例:

Constructor[] cons = c1.getConstructors();

		Class[] parmsType = cons[0].getParameterTypes(); //得到参数的类型
Object[] parms = new Object[parmsType.length]; //这个数组用来为newInstance()传参 //遍历parmsType数组,并为Object数组赋值
for(int i = 0 ; i < parms.length ; ++i)
{
if(parmsType[i].isPrimitive()) //判断是否是基本数据类型
{
parms[i] = new Integer(100);
}
}

此时就可以创建Point对象了:

Point pt = (Point)cons[0].newInstance(parms);

此时,我们看到控制台打印出100,说明Point类构造成功。

3.调用Class所对应类的成员方法

先通过Class的getDeclaredMethods()方法来得到所有被声明的方法,即返回一个Method[]类型的数组。然后可以调用Method对象的invoke()方法实现方法的调用。invoke()依然分有参和无参两种情况。此时的调用方式与上面调用newInstance()的过程类似,不再赘述。

三、反射的缺点:(从官方指南上找的,个人翻译水平差,大家凑合看。。。。意会就行。。)

Reflection is powerful, but should not be used indiscriminately. If it is possible to perform an operation without using reflection, then it is preferable to avoid using it. The following concerns should be kept in mind when accessing code via reflection.

尽管反射非常强大,但也不能滥用。如果一个功能可以不用反射完成,那么最好就不用。在我们使用反射技术时,下面几条内容应该牢记于心:

性能第一 
Performance Overhead

Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.

反射包括了一些动态类型,所以JVM无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。我们应该避免在经常被 执行的代码或对性能要求很高的程序中使用反射。

安全限制 
Security Restrictions

Reflection requires a runtime permission which may not be present when running under a security manager. This is in an important consideration for code which has to run in a restricted security context, such as in an Applet.

使用反射技术要求程序必须在一个没有安全限制的环境中运行。如果一个程序必须在有安全限制的环境中运行,如Applet,那么这就是个问题了。。

内部暴露 
Exposure of Internals

Since reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing 
private fields and methods, the use of reflection can result in unexpected side-effects, which may render code dysfunctional and may destroy portability. Reflective code breaks abstractions and therefore may change behavior with upgrades of the platform.

由于反射允许代码执行一些在正常情况下不被允许的操作(比如访问私有的属性和方法),所以使用反射可能会导致意料之外的副作用--代码有功能上的错误,降低可移植性。反射代码破坏了抽象性,因此当平台发生改变的时候,代码的行为就有可能也随着变化。

反射API的更多相关文章

  1. PHP 高级编程(2/5) - 反射API

    PHP 5 具有完整的反射 API,添加了对类.接口.函数.方法和扩展进行反向工程的能力. 此外,反射 API 提供了方法来取出函数.类和方法中的文档注释.通过使用反射API可以分析其他的类.接口.方 ...

  2. 了解一下OOP的反射API

    PHP5的类和对象函数并没有告诉我们类内部的所有一切,而只是报告了它们的公共成员.要充分了解一个类,需要知道其私有成员和保护成员,还要知道其方法所期望的参数 .对此,使用反射API. 1 查看自定义类 ...

  3. PHP反射API

    近期忙着写项目,没有学习什么特别新的东西,所以好长时间没有更新博客.我们的项目用的是lumen,是基于laravel的一个轻量级框架,我看到里面用到了一些反射API机制来帮助动态加载需要的类.判断方法 ...

  4. 反射——反射API,使用反射创建数组

    反射API Java.lang.Reflect库 ①   Class类与Java.lang.Reflect类库一起对反射的概念进行支持. ②   java.lang包下: a)         Cla ...

  5. Java学习笔记--反射API

    反射API 1.反射API的介绍 通过反射API可以获取Java程序在运行时刻的内部结构.比如Java类中包含的构造方法.域和方法等元素,并可以与这些元素进行交换.     按照 一般地面向对象的设计 ...

  6. 详解PHP反射API

    PHP中的反射API就像Java中的java.lang.reflect包一样.它由一系列可以分析属性.方法和类的内置类组成.它在某些方面和对象函数相似,比如get_class_vars(),但是更加灵 ...

  7. Java反射API研究(1)——注解Annotation

    注解在表面上的意思,只是标记一下这一部分,最好的注解就是代码自身.而在java上,由于注解的特殊性,可以通过反射API获取,这种特性使得注解被广泛应用于各大框架,用于配置内容,代替xml文件配置. 要 ...

  8. JDK1.7新特性(4):java语言动态性之反射API

    直接通过一个代码示例来熟悉java中通过反射来对构造函数/域以及方法处理的相关API: package com.rampage.jdk7.chapter2; import java.lang.refl ...

  9. PHP面向对象深入研究之【了解类】与【反射API】

    了解类 class_exists验证类是否存在 <?php // TaskRunner.php $classname = "Task"; $path = "task ...

  10. Atitit.跨语言反射api 兼容性提升与增强 java c#。Net  php  js

    Atitit.跨语言反射api 兼容性提升与增强 java c#.Net  php  js 1. 什么是反射1 1.1.       反射提供的主要功能:1 1.2.       实现反射的过程:1 ...

随机推荐

  1. ViewPager实现启动引导页面(个人认为很详细)

    效果如图: 启动页面是一张图片+延时效果,这里就不给出布局文件了. WelcomeActivity分析:在启动页面检测是否是第一次运行程序,如果是,则先跳转到引导界面的Activity——AndyVi ...

  2. 使用ownCloud在Linux安装你的个人云服务

    ownCloud是一个免费开源的软件,用于为分享文件,日历,联系人,书签和个人音频/视频.非常容易安装和管理. 前提 在这篇教程里我使用CentOS 6.5 minimal server来安装ownC ...

  3. Strange Country II 暴力dfs

    这题点的个数(<=50)有限, 所以可以纯暴力DFS去搜索 //#pragma comment(linker, "/STACK:16777216") //for c++ Co ...

  4. 鼠标滑轮一滚动Excel就停止工作

    鼠标滑轮一滚动Excel就停止工作 问题签名: 问题事件名称:APPCRASH 应用程序名:EXCEL.EXE 应用程序版本:15.0.4420.1017 应用程序时间戳:50673286 故障模块名 ...

  5. 第一次PS练习

    嘿嘿,自己第一次的PS,虽然把在大神眼里是小KS,但是了,对我来说值得劲纪念.加油,我会努力的.

  6. 动画api说明

    1.Animation的API参考文档:http://blog.csdn.net/harvic880925/article/details/40117115 2.动画插值器的参考: http://bl ...

  7. Vmware Briged方式使虚拟机上网

    1.禁用掉在网络连接VMware Network Adapter VMnet1和VMware Network Adapter VMnet8 (在bridged这种方式下不需要这两个连接,如下图) 2. ...

  8. Linux fstab 参数详解

    [root@qs-wg-db1 /]# cat /etc/fstab LABEL=/          /                       ext3    defaults         ...

  9. [poj 1265]Area[Pick定理][三角剖分]

    题意: 给出机器人移动的向量, 计算包围区域的内部整点, 边上整点, 面积. 思路: 面积是用三角剖分, 边上整点与GCD有关, 内部整点套用Pick定理. S = I + E / 2 - 1 I 为 ...

  10. JavaScript实现获取table中某一列的值

    JavaScript实现获取table中某一列的值 1.实现源代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional/ ...