反射API

时间:2022-01-18 01:55:07

反射,是指一种能在运行时动态加载、分析类的能力。反射被广泛地用于那些需要在运行时检测或修改程序行为的程序中。这是一个相对高级的特性,使用反射技术应当具备相当的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 高级编程&lpar;2&sol;5&rpar; - 反射API

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

  2. 了解一下OOP的反射API

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

  3. PHP反射API

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

  4. 反射——反射API&comma;使用反射创建数组

    反射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研究&lpar;1&rpar;——注解Annotation

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

  8. JDK1&period;7新特性&lpar;4&rpar;&colon;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&period;跨语言反射api&&num;160&semi;兼容性提升与增强&&num;160&semi;java&&num;160&semi;c&num;。Net&&num;160&semi;&&num;160&semi;php&&num;160&semi;&&num;160&semi;js

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

随机推荐

  1. JEECMS v8 发布,java 开源 CMS 系统

    JEECMSv8 是国内java开源CMS行业知名度最高.用户量最大的站群管理系统,支持栏目模型.内容模型交叉自定义.以及具备支付和财务结算的内容电商为一体:  对于不懂技术的用户来说,只要通过后台的 ...

  2. linux概念之进程分析

    http://blog.csdn.net/kevinx_xu/article/details/8178746 /proc 详解 内核线程分析报告 进程层次 [root@109-com1 scripts ...

  3. CISCO ASA 防火墙 IOS恢复与升级

    在IOS被误清除时的处理办法: 1.从tftp上的ios启动防火墙 防火墙启动后 ,按“ESC”键进入监控模式 rommon #2> ADDRESS=192.168.1.116 rommon # ...

  4. uva 387 A Puzzling Problem (回溯&rpar;

     A Puzzling Problem  The goal of this problem is to write a program which will take from 1 to 5 puzz ...

  5. Nopi Excel导入

    http://download.csdn.net/detail/diaodiaop/7611721 using System.Collections.Generic; using System.Dat ...

  6. 小草手把手教你 LabVIEW 串口仪器控制——VISA 串口配置

    建议大家按我发帖子的顺序来看,方便大家理解.请不要跳跃式的阅读.很多人现在看书,都跳跃式的看,选择性的看,导致有些细节的部分没有掌握到,然后又因为某个细节耽误很多时间.以上只是个人建议,高手可以略过本 ...

  7. 秋名山老司机(BS4与正则的比拼)

    因为嘉伟思杯里的一个脚本题目,16进制计算,python3正则还没学,所以没写出来.大佬跟我说也可以用BS4,从DOM上下手,直接爬下来直接一个eval就搞定了,eval可以像这样计算16进制,eva ...

  8. 与引导文件系统&sol;vmfs&sol;devices&period;&period;的备用设备之间的连接已丢失,主机配置更改将不会保存到持久存储中

    Cisco UCS 刀片服务器与NETAPP存储 1.异常问题描述: 2.可能原因:存储链路异常     比如断电恢复.光纤线本身的问题.模块的问题.环境温度的问题.bug之类的都有可能 3.处理: ...

  9. Android笔记:OptionsMenu

    使用菜单选项OptionsMenu,需要进行以下操作:(1)重写onCreateOptionsMenu方法: public boolean onCreateOptionsMenu(Menu menu) ...

  10. 【android开发】如何在Linux平台下安装JDK环境

    原文:http://android.eoe.cn/topic/android_sdk Linux平台JDK安装 本文主要描述如何在Linux平台下安装JDK环境.进入网页:http://www.ora ...