序言

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

从这个观点来看,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. 走进javascript——解开switch之谜

    很早以前就觉得switch很怪异,或者说一直没太理解它,它怪异就怪异在非要给每个语句加上break;不然后面的语句就算不符合条件还是会执行,比如以下这段代码 var num = 2; switch(n ...

  2. 编程思想之——"人是活的,程序是死的"

    "人是活的,程序是死的"这句话我时常提起,可能很多人不是很理解我为什么会这样说,下面我就简单来谈谈我对这句话的理解. 1.不要因为技术而技术,技术选型的初衷是需求. 现在很多人在做 ...

  3. SqlService 索引原理

    索引的概念 索引的用途:我们对数据查询及处理速度已成为衡量应用系统成败的标准,而采用索引来加快数据处理速度通常是最普遍采用的优化方法. 索引是什么:数据库中的索引类似于一本书的目录,在一本书中使用目录 ...

  4. spring init

    DN学院讲师招募     Markdown编辑器轻松写博文     TOP 50 CTO坐镇直招     读文章说感想获好礼 通过Spring @PostConstruct 和 @PreDestroy ...

  5. 香港多IP站群服务器-搭建多IP代理服务器、游戏加速服务器

    耀磊花楹qq82521463香港WK自营机房多IP服务器租用,多IP站群服务器,多IP多C段 站群服务器租用 耀磊数据拥有3万个自由香港IP以及独立AS号,是APNIC核心成员,机房通过BGP融合 多 ...

  6. 或许是介绍Android Studio使用Git最详细的文章

    欢迎访问我的个人博客转发请注明出处:http://www.wensibo.top/2017/03/12/GitOnAS/ 前言 本文较长,图片很多很多,流量党慎入 使用Git已经有一段时间了,但是之前 ...

  7. 关于mvc中传入DataTable到视图的应用

    MVC 中 如果是多表连接查询出的数据需要重新定义一个ViewModel,觉得很是麻烦,所以可以通过传一个DataTable到视图中可以避免这个问题 但是不知道会有什么不好的地方,有这方面经验的大神有 ...

  8. ajax详细讲解和封装包括HTTP状态码

    AJAX(异步的JavaScript和XML,用异步的形式去操作xml) 主要的作用:数据交互   好处:               1.节省用户的操作时间               2.提高用户 ...

  9. Vue学习之路---No.6(分享心得,欢迎批评指正)

    我们还是先回顾一下上一次的重点: 1.事件绑定,我们可以对分别用方法和js表达式对事件进行处理 2.当方法名带括号的时候,在方法中一定要传参:而不带括号的时候,vm会自动配置默认event 3.各类事 ...

  10. android 中判断WiFi是否可用的可靠方法 ,android 是否联网

    http://alex-yang-xiansoftware-com.iteye.com/blog/619841 在一些程序中,需要从网上下载数据,或者通过其他方式对网络产生流量,当wifi不可用时应该 ...