`

反射基础概念

阅读更多
这种动态的获取信息及动态调用方法的机制在Java中称为“反射”(reflection)。
Java反射机制主要提供以下功能:

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

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


一般而言,开发者社群说到动态语言,大致认同的一个定义是:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。


在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中:
Class类:代表一个类;
Field 类:代表类的成员变量(成员变量也称为类的属性);
Method类:代表类的方法;
Constructor 类:代表类的构造方法;
Array类:提供了动态创建数组,以及访问数组的元素的静态方法;

在java.lang.Object 类中定义了getClass()方法,因此对于任意一个Java对象,都可以通过此方法获得对象的类型。Class类是Reflection API 中的核心类,它有以下方法:
getName():获得类的完整名字;
getFields():获得类的public类型的属性(包括继承的类的public属性);
getDeclaredFields():获得类的所有属性;
getMethods():获得类的public类型的方法; (包括继承的类的public方法);
getDeclaredMethods():获得类的所有方法;
getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型;
getConstructors():获得类的public类型的构造方法;
getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型;
newInstance():通过类的不带参数的构造方法创建这个类的一个对象;

(2)通过默认构造方法创建一个新对象:
Object objectCopy=classType.getConstructor(new Class[]{}).newInstance(new Object[]{});
以上代码先调用Class类的getConstructor()方法获得一个Constructor 对象,它代表默认的构造方法,然后调用Constructor对象的newInstance()方法构造一个实例。



(3)获得对象的所有属性:
Field fields[]=classType.getDeclaredFields();
Class 类的getDeclaredFields()方法返回类的所有属性,包括public、protected、默认和private访问级别的属性。
import java.lang.reflect.Array;     

public class ArrayTester1     
{     
public static void main(String args[]) throws Exception     
{     
Class<?> classType = Class.forName("java.lang.String");     
// 创建一个长度为10的字符串数组     
Object array = Array.newInstance(classType, 10);     
// 把索引位置为5的元素设为"hello"     
Array.set(array, 5, "hello");     
// 获得索引位置为5的元素的值     
String s = (String) Array.get(array, 5);     
System.out.println(s);     
}     



Java允许我们从多种途径为一个class生成对应的Class object。



(一)运用getClass()方法:

String str = "abc";

Class class = str.getClass();



(二)运用Class.getSuperclass()方法:

Button b = new Button();

Class c1 = b.getSuperclass();

Class c2 = c1.getSuperclass();



(三)运用静态方法Class.forName(),这个最常用:

Class c1 = Class.forName("java.lang.String");

Class c2 = Class.forName("java.util.Date");



(四)运用.class语法:

Class c1 = String.class;

Class c2 = java.awt.Button.class;

Class c3 = int.class;

Class C4 = int[].class;



(五)运用原始包装类的TYPE方法:

Class c1 = Integer.TYPE;

Class c2 = Character.TYPE;

Class c3 = Boolean.TYPE;

Class c4 = Void.TYPE;


通过这五种方法,可以生成我们想要的类对象。


其他


类加载器ClassLoader


类加载器就是寻找类或接口字节码文件进行解析并构造JVM内部对象表示的组件,在Java中,类加载器把一个类装入JVM中,要经过以下几个步骤:
1.装载,查找和导入Class文件。
2.连接,执行校验,准备和解析步骤,其中解析步骤是可以选择的。
校验:检查载入Class文件数据的正确性。
准备:给类的静态变量分配内存空间。
解析:将符号引用转换成直接引用。
3.初始化:对类的静态变量,静态代码块执行初始化工作。
类装载工作由ClassLoader及其子类负责,ClassLoader是一个重要的Java运行时系统组件,他负责运行时查找和装入Class字节文件。JVM在运行时会生成三个ClassLoader,根装载器,ExtClassLoader(扩展类装载器)和AppClassLoader(系统类装载器)其中根装载器我们在Java中看不到它,它负责装载JRE的核心类库,ExtClassLoader负责装载JRE扩展目录ext中的JAR类包,AppClassLoader负责装载Classpath路径下的类包。这三个类装载器之间存在父子层级关系,根装载器是ExtClassLoader的父装载器,ExtClassLoader是AppClassLoader的父装载器。默认情况下使用AppClassLoader装载应用程序的类。
JVM装载类时使用“全盘负责委托机制”,“全盘负责”是指当一个ClassLoader装载一个类时,除非显示地使用另一个ClassLoader,该类所依赖及引用的类也由这个ClassLoader载入,“委托机制”是指委托父类装载器寻找目标类,只有在找不到的情况下才从自己的类路径中查找并装载目标类,这一点是从安全角度考虑的。试想如果有人编写一个恶意的java.lang.String并装载到JVM中将会引起什么可怕的后果,但是由于有了全盘负责制,java.lang.String永远都是由根装载器来装载的。

ClassLoader重要方法:


在Java中,ClassLoader是一个抽象类,位于Java.lang包中,下面对该类的一些重要接口方法进行介绍:


Class loaderClass(String name): name参数指定类装载器需要装载类的名字,必须使用全限定类型(包名+类名)该方法有一个重载方法loaderClass(String name,boolean resolve)其中resolve参数告诉类装载器是否需要解析该类,在初始化之前,应考虑进行类解析工作,但并不是所有的类都需要解析,如果JVM只需要知道该类是否存在或找出该类的超类,那么就不需要进行解析。


Class defineClass(String name,byte[] bt,int off,int len): 将类文件的字节数组转换成JVM内部的java.lang.Class对象,字节数组可以从本地文件系统,远程网络获取,name为字节数组对象的全限定名。
Class findSystemClass(String name):从本地文件系统载入Class文件,如果本地文件系统不存在该Class文件,将抛出ClassNotFoundException异常。该方法是JVM默认的装载机制。


Class findLoadedClass(String name)调用该方法来查看ClassLoader是否已装入某个类,如果已装入那么返回java.lang.Class对象,否则返回null,如果强行装载已存在的类,将会抛出链接错误。
ClassLoader getParent()获取类装载器的父装载器,除根装载器之外,所有的类装载器都有仅有一个父类装载器。除了JVM默认的三个ClassLoader以外,第三方可以编写自己的类装载器,以显现一些特殊的需求,类文件被装载并解析后,在JVM将拥有一个对应的java.lang.Class类描述对象。该类的实例都拥有指向这个类描述对象的引用,而类描述对象又拥有指向关联ClassLoader的引用。


每一个类在JVM中都拥有一个对应的java.lang.Class对象,他提供了类结构信息的描述,数组,枚举,以及基本的Java类型,甚至void都拥有对应Class对象,Class没有public的构造方法,Class对象是在装载类时由JVM通过调用类装载器中的defineClass()方法自动创造的。
Java的反射机制:通过以上的介绍我们可以看到Class反射对象描述类语义结构,可以Class对象中获取构造函数,成员变量,方法类等类元素的反射对象,并以编程的方式通过这些反射对象对目标类对象进行操作。这些反射类对象在java.reflect包中定义。下面介绍主要的三个反射类:


Constructor:类构造函数反射类,通过Class.getConstructors()方法可以获得类的所有构造函数反射对象数组。在JDK5.0以上的版本我们可以使用getConstructors(Class[] paramerTypes)获取拥有特定入参的构造函数反射对象。Constructor的一个主要方法是newInstance(Object[] initargs)通过该方法我们可以创建一个对象类的实例,相当于使用new关键字。
Method:类方法的反射类,通过Class.getDeclaredMethods()方法可以获取类的所有方法放射对象数组Method[],在JDK5.0以上的版本我们可以使用getDeclaredMethods(String name,Class parameterTypes)获取特定签名方法,name为方法名,Class为方法入参列表,

Method最主要的方法是invoke(Object obj,Object[] arges)obj为操作目标对象,arges为方法入参。 
Method 还有很多用于获取类方法更多信息的方法。 
Class getRetunType():获取方法的返回值类型。
Class getParameterTypes():获取方法的入参类型数组。等等...更多方法参见API。


Field:类的成员变量的反射类,通过Class#getDeclaredFields()方法可以获取类的成员变量反射对象数组,通过getDeclaredFields(String name)则可以获取某个特定名称的成员变量反射对象。Field类主要的方法是:set(Object obj, Object value) obj表示操作的目

标对象,通过value为目标对象的成员变量设置值,如果成员变量为基础类型,用户可以使用Field类中提供的带类型名的值设置方法。如

setBoolean(Object obj,Boolean value).
在JDK5.0以上还为包及注解提供了AnnotatedElement反射类,总之:Java的反射体系保证了可以通过程序化的方式访问目标类中的所有元素,对于private或protected的成员变量和方法,只要是JVM的安全机制允许,也可以通过反射机制进行调用。


我们只需要用setAccessible(Boolean bool)方法进行设置就可以取消访问修饰符的限制。
true表示取消Java语言访问限制,flase表示不取消访问限制。如果在访问private,protected成员变量和方法时没有设置是否取消限制则会抛出IllegalAccessException.如果JVM的安全管理器设置相应的安全机制,调用该方法将抛出SecurityException。

分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    PHP进阶学习之反射基本概念与用法分析

    本文实例讲述了PHP进阶学习之反射基本概念与用法。分享给大家供大家参考,具体如下: 一、前言 Reflection(反射)是Java程序开发语言的特征之一,它允许运行中的Java程序对自身进行检查,或者说“自审”,并能直接...

    框架的概念及用反射技术开发框架的原理

    Java基础加强_框架的概念及用反射技术开发框架的原理

    Java反射.doc

    Java反射基本概念,使用场景,性能分析,附录 1.Java内存模型,JVM加载过程

    JAVA新特性--java反射、映射

    开放性和原因连接是反射系统的两大基本要素。13700863760 Java中,反射是一种强大的工具。它使您能够创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代表链接。反射允许我们在编写与执行时,使...

    论文研究-基于代数语义的反射系统研究 .pdf

    基于代数语义的反射系统研究,滕冀,,本文介绍了反射和反射系统的基本概念,代数语义的一些基本定义,并在代数语义定义的基础上, 形式化地描述了反射的语义。同时在�

    visual basic.net 反射参考手册

    本书全面介绍了反射的概念及其相关应用技术,内容包括使用动态绑定的原因以及Reflection API支持它的方式;检测程序集类等元数据;自由加载程序集并创建对象和调用方法;利用反射修改对象数据;使用属性控制编译过程...

    xml与反射.txt

    机制这个概念,所以就对不同的表创建不同的dao类,这样不仅开发速率慢,而且代码冗余的厉害,最要命的是看着差不多 的,然后直接复制修改,由于容易犯各种低级的错误(大小写啊,多一个或少一个字母啊……),一个错误...

    Java反射基础入门,一篇就够啦

    文章目录Java基础之反射1 前言2 反射的基本概念3 reflection的工作机制4 构造Class对象方式5 Java反射机制操作的基础套路5.1 Java中的类反射5.2 Java反射机制获取类中构造方法的信息5.3 获取类中方法的信息6 Java...

    JAVA反射知识点总结

    本文介绍了JAVA反射类的基本概念,欢迎阅读学习,一起进步。 文章目录一.反射的基本概念二.反射常用类三.使用反射的基本步骤四.Class类讲解(1)Class类是反射机制的起源和入口(2)Class类存放类的结构信息(3)...

    信号完整性之 信号的反射

    文章介绍了信号的反射的基本概念,反射机理与消除反射的端接方法

    JavaSE进阶-08-反射机制1

    1.1 反射的基本概念 1.2 Java 中的类反射 2.2.1 2.2.2

    C#基础概念.doc

    C#基础概念: 1、静态变量和非静态变量的区别? 2、const 和 static readonly 区别? 3、extern 是什么意思? 4、abstract 是什么意思? 5、internal 修饰符起什么作用? 6、sealed 修饰符是干什么的? 7、override...

    Java基础学习教程(附PPT和源代码)

    适彻分析反射的基础 Class类rar 理解反射的概念.rar 构造方法的反射应用.rar 成员变量的反射.rar 成员变量反射的综合案例.rar 成员方法的反射.rar 对接收数组参数的成员方法进行反射....数组与Object的关系及其反射...

    你必须知道的C#的25个基础概念(附源码)

    什么是反射? 以下是我做的一份参考答案(C# 语言范畴之内),如果有不准确、不全面的,欢迎各位朋友指正! 1.静态变量和非静态变量的区别?答:静态变量:静态变量使用 static 修饰符进行声明在所属类被装载时创建...

    ES6 如何改变JS内置行为的代理与反射

    一、代理与反射的基本概念 什么是代理和反射呢? 代理是用来替代另一个对象(target),JS 通过new Proxy()创建一个目标对象的代理,该代理与该目标对象表面上可以被当作同一个对象来对待。 当目标对象上的进行...

    c# 中 反射的用法

    在网上查找了不少的资料,可以说大同小异,概念...今天把反射的东西整理了一下,供大家使用,我保证我这里是最全面的东西,当然也是基础的东西, 在学好了这一切的基础上,大家可以学习反射的具体插件等应用,老鸟就不用看了.

    遥感技术应用课件:遥感概念及特点.pptx

    遥感的基本概念 应用探测仪器,不与探测目标接触,从远处用把目标的电磁波特性记录下来,通过对信息的处理和分析研究,揭示出物体的特征、性质及其变化的综合性探测技术。 戈壁滩遥感影像 戈壁滩遥感影像 遥感的基本...

    硬件设计/电路设计+信号完整性/SI+基础知识概念思维导图

    该思维导图以信号完整性为核心概念,辐射出信号保真度、信号时序、信号阻抗、反射与串扰、S参数等关键知识点。这些知识点彼此关联,形成一个完整且实用的思维导图。 信号完整性是电子工程中一个关键概念,它关乎到...

    Java反射技术原理与用法实例分析

    主要介绍了Java反射技术原理与用法,结合实例形式分析了Java反射技术的基本概念、功能、原理、用法及操作注意事项,需要的朋友可以参考下

Global site tag (gtag.js) - Google Analytics