序言

一般而言,动态语言是指程序运行时,允许改变程序结构或变量类型的语言。

从这个观点来看,Perl、Python、Ruby是动态语言,C++、Java、C#不是动态语言。

但是Java有动态相关机制:Reflection,反射,是指可以运行时加载、探知、使用编译期间完全未知的Classes。

一、什么是反射?

Java程序可以加载一个运行时才得知名称的Class,获取其完整构造,并生成其对象实体,设置属性,调用方法。

这种动态获取类信息以及动态调用对象方法的功能就是Java语言的反射机制。

二、反射的作用?

1、在运行时判断任意一个对象所属的类

2、在运行时构造任意一个类的对象

3、在运行时判断任意一个类所具有的成员变量和方法

4、在运行时调用任意一个对象的方法

三、反射的一些概念

1、反射相关的类和接口,都放在软件包java.lang.reflect

软件包java.lang.reflect提供类和接口,以获取关于类和对象的反射信息。

在安全限制内,反射允许编程访问关于加载类的字段、方法和构造方法的信息,并允许使用反射字段、方法和构造方法对对象上的基本对等项进行操作。

如果必需的 ReflectPermission 可用,则 AccessibleObject 允许抑制访问检查。Array 提供动态创建和访问数组的静态方法。

此包中的类以及 java.lang.Class 可以适应以下应用程序的需要:调试程序、解释程序、对象检查程序、类浏览程序等。

2、反射相关类摘要

类名 说明
AccessibleObject AccessibleObject 类是Field、Method 和 Constructor 对象的基类。
Constructor<T> Constructor提供关于类的单个构造方法的信息以及对它的访问权限。
Field Field提供有关类或接口的单个字段的信息,以及对它的动态访问权限。
Method Method提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。
Modifier Modifier类提供了static方法和常量,对类和成员访问修饰符进行解码。
Proxy Proxy提供用于创建动态代理类和实例的静态方法,它还是由这些方法创 建的所有动态代理类的超类。
ReflectPermission 反射操作的Permission类。

3、java.lang.Class说明

Class 类和一般类一样继承自 Object ,其实体用以表达 Java 程序运行时的类和接口,枚举,数组,基础类型(boolean, byte, char, short, int, long, float, double)以及关键词void。

Class 没有公共构造方法。当一个 Class 被加载,或当加载器(class loader)的 defineClass() 被 JVM 调用, JVM 便自动产生一个类对象 。

Java 有个 Object 类,是所有 Java 类的继承根源,其内声明了数个应该在所有 Java 类中被改写的方法: hashCode()、equals()、clone() 、toString() 、getClass() 等。

其中 getClass() 返回一个 Class 类的对象,因此对于任意一个 Java 对象,都可以通过此方法获得对象的类型。

===Class 类是 Reflection API 中的核心类,它有以下方法===

getName() :获得类的完整名字。

getFields() :获得类的 public 类型的属性。

getDeclaredFields() :获得类的所有属性。

getMethods() :获得类的 public 类型的方法。

getDeclaredMethods() :获得类的所有方法。

getMethod(String name, Class[] parameterTypes) :获得类的特定方法, name 参数指定方法的名字, parameterTypes 参数指定方法的参数类型。

getConstructors() :获得类的 public 类型的构造方法。

getConstructor(Class[] parameterTypes) :获得类的特定构造方法, parameterTypes 参数指定构造方法的参数类型。

newInstance() :通过类的不带参数的构造方法创建这个类的一个对象。

四、反射的具体实现

反射用到的测试类:含测试用的方法和属性

package code.lemon;

import java.util.Map;
import java.util.Set;
import java.util.List; public class Pear{
Map<String, String> map;
public Set<String> set;
public Class<?> clazz;
String str;
Set set1;
public List<String> list; private static Pear pear;
static{
pear = new Pear();
} private Pear(){
} public Pear(String str){
this.str = str;
} public static void main(String [] args){
System.out.println(Pear.class.getPackage());
} public String getStr(){
return str;
} private void setStr(String str){
this.str = str;
}
}

1、获取类的构造方法

public static void printConstructor(String className) {
try {
Class<?> clazz = Class.forName(className);
//返回一个包含某些 Constructor 对象的数组,
//这些对象反映此 Class 对象所表示的类的所有公共构造方法。
Constructor<?>[] constructors = clazz.getConstructors();
for (int i = 0; i < constructors.length; i++) {
System.out.println(constructors[i]);
}
System.out.println("------------------");
//返回 Constructor 对象的一个数组,
//这些对象反映此 Class 对象表示的类声明的所有构造方法。
Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
for (int i = 0; i < declaredConstructors.length; i++) {
//返回此类或接口以整数编码的 Java 语言修饰符。
int modifiers = declaredConstructors[i].getModifiers();
System.out.println(declaredConstructors[i] + ":"
+ Modifier.toString(modifiers));
}
} catch (Exception e) {
}
}

2、获取类属性

public static void printField(String className) {
try {
Class<?> clazz = Class.forName(className);
//返回一个包含某些 Field 对象的数组,
//这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。
Field[] fields = clazz.getFields();
for (int i = 0; i < fields.length; i++) {
System.out.println(fields[i]);
}
System.out.println("------------------");
//返回 Field 对象的一个数组,
//这些对象反映此 Class 对象所表示的类或接口所声明的所有字段,
//包括公共、保护、默认(包)访问和私有字段,但不包括继承的字段。
Field[] declaredFields = clazz.getDeclaredFields();
for (int i = 0; i < declaredFields.length; i++) {
int modifiers = declaredFields[i].getModifiers(); System.out.println(declaredFields[i] + ":"
+ Modifier.toString(modifiers));
}
} catch (Exception e) {
}
}

3、获取类方法

public static void printMethod(String className) {
try {
Class<?> clazz = Class.forName(className);
//返回一个包含某些 Method 对象的数组,
//这些对象反映此 Class 对象所表示的类或接口
//包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口的公共方法。
Method[] methods = clazz.getMethods();
for (int i = 0; i < methods.length; i++) {
System.out.println(methods[i]);
}
System.out.println("------------------");
//返回 Method 对象的一个数组,
//这些对象反映此 Class 对象表示的类或接口声明的所有方法,
//包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
Method[] declaredMethods = clazz.getDeclaredMethods();
for (int i = 0; i < declaredMethods.length; i++) {
int modifiers = declaredMethods[i].getModifiers(); System.out.println(declaredMethods[i] + ":"
+ Modifier.toString(modifiers));
} } catch (Exception e) {
}
}

4、私有方法的调用

public static void invokeMethod(String className) {
try {
Class<?> clazz = Class.forName(className);
//Pear pear = new Pear("hello");
Object pear = clazz.getConstructor(new Class[]{}).newInstance(new Object[]{});
//返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。
//name 参数是一个 String,它指定所需方法的简称,
//parameterTypes 参数是 Class 对象的一个数组,它按声明顺序标识该方法的形式参数类型。
Method declaredMethod = clazz.getDeclaredMethod("setStr", new Class[]{String.class});
//对所有属性设置访问权限 当类中的成员变量为private时 必须设置此项
declaredMethod.setAccessible(true);
//对带有指定参数的指定对象调用由此 Method 对象表示的基础方法。
declaredMethod.invoke(pear, new Object[]{"world"}); Method declaredMethod1 = clazz.getDeclaredMethod("getStr", new Class[]{});
Object result = declaredMethod1.invoke(pear, new Object[]{}); System.out.println((String)result);
} catch (Exception e) {
}
}

5、动态创建、访问数组

public static void printArray() {
try{
Class <?> classType = Class.forName("java.lang.String");
//newInstance创建此 Class 对象所表示的类的一个新实例。
Object array = Array.newInstance(classType, 10);
Array.set(array, 5, "hello");
for(int i =0;i < Array.getLength(array);i ++){
String str = (String)Array.get(array,i);
System.out.println(str);
}
}catch(Exception e){
}
}

本例的包名为code.lemon,参数className为"code.lemon.Pear"

五、具体代码如下

代码下载地址

Java反射理解的更多相关文章

  1. Java反射理解(五)-- 方法反射的基本操作

    Java反射理解(五)-- 方法反射的基本操作 方法的反射 1. 如何获取某个方法 方法的名称和方法的参数列表才能唯一决定某个方法 2. 方法反射的操作 method.invoke(对象,参数列表) ...

  2. Java反射理解(四)-- 获取成员变量构造函数信息

    Java反射理解(四)-- 获取成员变量构造函数信息 步骤 获取成员变量信息: obj.getClass() 获取类类型对象 成员变量也是对象,java.lang.reflect.Field 类中封装 ...

  3. Java 反射理解(三)-- Java获取方法信息

    Java 反射理解(三)-- Java获取方法信息 基本的数据类型.void关键字,都存在类类型. 举例如下: public class ClassDemo2 { public static void ...

  4. Java 反射理解(二)-- 动态加载类

    Java 反射理解(二)-- 动态加载类 概念 在获得类类型中,有一种方法是 Class.forName("类的全称"),有以下要点: 不仅表示了类的类类型,还代表了动态加载类 编 ...

  5. Java 反射理解(一)-- Class 类的使用

    Java 反射理解(一)-- Class 类的使用 概念 这里阐述几个基本概念: 在面向对象的世界里,万事万物皆对象.(在 Java 语言中,静态的成员.普通数据类型除外) 类也是对象,类是 java ...

  6. Java反射机制的学习

    Java反射机制是Java语言被视为准动态语言的关键性质.Java反射机制的核心就是允许在运行时通过Java Reflection APIs来取得已知名字的class类的相关信息,动态地生成此类,并调 ...

  7. Java反射机制(转载)

    原文链接:http://www.blogjava.net/zh-weir/archive/2011/03/26/347063.html Java反射机制是Java语言被视为准动态语言的关键性质.Jav ...

  8. (转载)Java反射机制

    Java反射机制是Java语言被视为准动态语言的关键性质.Java反射机制的核心就是允许在运行时通过Java Reflection APIs来取得已知名字的class类的相关信息,动态地生成此类,并调 ...

  9. java反射机制 + Method.invoke解释 getMethod + 反射理解

    功能: 通过读取另一个Dll去创建一个控件(Form,Button,TextBox,DataGridView),然后对当中一些属性进行检查. 创建控件的大致流程是,Assembly->Modul ...

随机推荐

  1. 【排序算法】归并排序算法 Java实现

    归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用. 基本思想 可以将一组数组分成A,B两组 依次类推,当分出来的小组只有一 ...

  2. js或者php浮点数运算产生多位小数的理解

    <?php $f = 0.58; var_dump(intval($f * 100)); //为啥输出57 ?> 首先我们要知道浮点数的表示(IEEE 754): 浮点数, 以64位的长度 ...

  3. 了解 : angular ng-messages

    ng-messages="form['positionTitle' + languageVersion.typeEnum].$error ng-messages="form.pos ...

  4. 了解 : EDM

    EDM是 Entity Data Meta,首先先了解什么是Entity. Entity 它是一个框架,在C#使用,方便调用SQL data的,和Odata 调用有关.细节我不清楚! EDM 基本是表 ...

  5. Azure Messaging-ServiceBus Messaging消息队列技术系列4-复杂对象消息是否需要支持序列化和消息持久化

    在上一篇中,我们介绍了消息的顺序收发保证: Azure Messaging-ServiceBus Messaging消息队列技术系列3-消息顺序保证 在本文中我们主要介绍下复杂对象消息是否需要支持序列 ...

  6. 用stm32f0x建立新的工程重要步骤

    stm32f10x系列新建空的工程主要原理: 1.添加启动文件 不同的芯片类型的启动文件的容量是不同的,选择适合该芯片的容量作为启动文件. 注意:启动文件是汇编语言编写的,所以文件的后缀名为.s 2. ...

  7. 基于 Koa平台Node.js开发的KoaHub.js的模板引擎代码

    koahub-handlebars koahub-handlebars koahub handlebars templates Installation $ npm install koahub-ha ...

  8. js/jQuery中load()、onload()、ready()的区别

    一.两大事件 load事件:指页面包含图片等文件在内的所有元素都加载完毕后执行的事件. ready事件:表示文档结构已加载完成(不包括图片等非文字媒体文件) 浏览器页面渲染的过程 - 寸寸君 - 博客 ...

  9. C++ Primer 5 CH1 开始

    1.1 编写一个简单的C++程序 在大多数系统中,main 的返回值被用来指示状态.返回值 0 表示成功,非 0 的返回值的含义由系统定义,通常用来指出错误类型. 访问 main 的返回值的方法依赖于 ...

  10. JavaWeb之Filter、Listener

    昨天和大家介绍了一下JSON的用法,其实JSON中主要是用来和数据库交互数据的.今天给大家讲解的是Filter和Listener的用法. 一.Listenner监听器 1.1.定义 Javaweb中的 ...