这种动态的获取信息及动态调用方法的机制在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进阶学习之反射基本概念与用法。分享给大家供大家参考,具体如下: 一、前言 Reflection(反射)是Java程序开发语言的特征之一,它允许运行中的Java程序对自身进行检查,或者说“自审”,并能直接...
在讨论C++反射机制实现的过程中,我们首先需要明确反射机制的概念和分类。反射的定义源自人工智能领域,它主要涉及到两种反射结构:结构反射和计算反射。结构反射侧重于元类与类之间的关系,计算反射则关注于计算...
2. **反射基本概念**:学习反射的基本操作,如`Class`类的使用,获取类、方法和字段的`java.lang.reflect`接口,如`Class.forName()`, `getMethod()`, `getField()`等。 3. **反射调用私有方法和字段**:通过反射,...
以下将详细介绍反射的基本概念、应用场景以及相关的API。 **反射基本概念** 1. **Introspection (内省)**:这是反射的核心,它赋予了Java程序检查自身的能力。通过内省,我们可以查看类的结构,包括包、类型参数、...
**1.1 反射基本概念** 反射是.NET框架中的一个重要特性,它允许程序在运行时动态地获取类型信息并操作类型。通过反射,程序员可以在不知道具体类型的情况下创建对象、调用方法、获取或设置字段值等。 **1.2 反射的...
1. **反射基本概念**:解释什么是反射,它的作用以及为什么我们需要它。反射允许程序在运行时动态地获取类的信息,并能创建和操作类的对象。 2. **Class类**:介绍`Class`对象,它是所有类的通用表示,通过`Class....
#### 二、反射基本概念 在深入探讨C#反射实例之前,我们首先了解几个关键的概念: - **Assembly(程序集)**:是.NET中的编译单元,包含了一组相关的类型和资源。 - **Type**:表示.NET Framework中的所有类型的抽象...
### 反射基本概念 反射基于Java的`java.lang.reflect`包,主要包含`Class`、`Constructor`、`Field`和`Method`四个核心类。它们分别代表类、构造器、字段和方法对象,可以用来获取类的信息和执行相关操作。 ### ...
根据提供的文件信息,本文将详细解释C#反射的基本概念、用途以及通过给出的代码示例来深入了解其工作原理。 ### C# 反射基本概念 C#中的**反射**是一种强大的功能,允许程序在运行时获取类型的信息并创建或操作...
1. 反射基本概念: 反射是.NET框架的核心组成部分,它提供了对程序集、类型、成员(如方法、属性、字段)以及元数据的访问。通过反射,我们可以在运行时获取关于类、接口、结构等类型的信息,并且可以动态创建对象...
反射是.NET框架中的一种强大机制...在学习和使用C#反射技术时,确保理解其基本原理和常见应用场景,同时注意控制反射的使用,以保持代码的效率和可维护性。通过熟练掌握反射,开发者可以构建更加灵活和强大的应用程序。
这篇PPT教案主要介绍了八年级物理中的光的反射知识,属于初中阶段的物理教学内容,主要面向学生和教师。...综上所述,这份PPT教案详细阐述了光的反射基本概念、定律及其应用,旨在帮助学生掌握和理解光的反射原理。
在了解了光的反射基本概念和分类之后,我们再来看一看光的反射在生活中的实际应用。例如,红宝石激光器、光纤通信和遥感技术等,都与光的反射原理息息相关。然而,光反射也有它的负面影响,如黑板反光或建筑玻璃幕墙...
综上所述,本资料详细地阐述了光的反射基本概念,实验探究反射定律的过程,以及镜面反射和漫反射的特性,并提供了相关例题来巩固理解。这些知识对于学习八年级物理的学生来说是非常重要的,有助于他们深入理解和掌握...
综上所述,本训练主要涵盖了生物学中关于反射的基本概念、分类、形成机制以及在高等动物中的重要性。通过这些知识的学习,学生可以理解生物体如何通过反射对外部环境做出快速有效的反应,并理解学习和记忆在条件反射...
一、Java反射基本概念 1. 类的Class对象:每个类都有一个对应的Class对象,它是运行时类信息的载体。通过`Class.forName()`或对象的`getClass()`方法可以获得此类的Class对象。 2. 字段(Field):代表类的成员变量...
1. 光的反射基础概念:首先,教师需向学生介绍光是什么,包括光的性质以及它与日常生活的关系。然后,讲解光的反射现象,即光在两种不同介质的界面上会发生反射,这取决于入射光和反射光相对于法线的角度关系。 2. ...
- 掌握光的反射基本概念,理解镜面反射和漫反射的区别。 - 熟悉并能应用光的反射定律解决实际问题。 - 提高观察和分析生活中光反射现象的能力。 9. **自主学习测评**: - 测评练习旨在检验学生对反射定律的理解...
1. **反射基本概念** 反射是.NET框架提供的一种能力,它允许程序在运行时获取关于自身的信息,并且能够根据这些信息动态地调用方法或访问属性。C#中的`System.Reflection`命名空间提供了反射相关的类,如`Type`、`...