序言

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

从这个观点来看,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. groovy学习(二)map

    names = ['Ken' : 'Barclay', 'John' : 'Savage']divisors = [4 : [2], 6 : [3, 2], 12 : [6, 4, 3, 2]]pri ...

  2. 令人费解的java泛型

         对于我们java中的泛型,可能很多人知道怎么使用并且使用的还不错,但是我认为想要恰到好处的使用泛型,还是需要深入的了解一下它的各种概念和内部原理.本文将尽可能的囊括java泛型中的重要的概念 ...

  3. centos7搭建nexus maven私服

    前置条件: 1.安装jdk,可参考 http://www.cnblogs.com/grey-wolf/p/6480489.html 2.nexus仓库管理器,分为两个版本,Nexus Reposito ...

  4. [bzoj1500][NOI2005]维修数列——splay

    题目 题解 这道题可以说是数列问题的大BOSS,也算是这一周来学习splay等数据结构的一个总结. 我们一个一个地看这些操作. 对于操作1,我们首先建一棵子树,直接接上原树即可. 对于操作2,我们找到 ...

  5. flex布局应用于踩坑

    一.预告 本文不是一篇入门的文章所有请符合以下条件的战斗人员绕道: 1.初学前端,对前端的传统布局还不是很熟悉的人 2.后端人员对前端不打算深入学习的同学 二.开篇 flex布局原本是好几个月前就一直 ...

  6. 剑指offer编程题Java实现——面试题12打印1到最大的n位数

    题目:打印1到最大的n位数 输入数字n,按顺序打印输出从1到最大的n位十进制数,比如输入3,打印从1到999. 这道题考察的地方是如何表示大数问题.由于n是任意大的数组,如果n太大的话n位数就超过了l ...

  7. 使用multer搭建一个图片接收服务器

    为了测试图片上传插件的上传功能是否好用,最近尝试搭建了一个接收图片的服务器,因为图片上传的编码格式是form-data,所以我选择使用express+multer,实现过程中发现有几个需要注意的地方, ...

  8. nodejs中的异步流程序控制nsync

    异步编程是指由于异步I/O等因素,无法同步获得执行结果时, 在回调函数中进行下一步操作的代码编写风格,常见的如setTimeout函数.ajax请求等等 http://cnodejs.org/topi ...

  9. Django之Cookie

    Cookie 在浏览器端(客户端)保存的键值对,特性:每次http请求都会携带.           举个例子:{"name":身份证号} 1丶获取cookie request.C ...

  10. java线程学习(二)

    多个线程并发抢占资源是,就会存在线程并发问题,造成实际资源与预期不符合的情况.这个时候需要设置"资源互斥". 1.创建资源,这个地方我创建了一个资源对象threadResource ...