序言

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

从这个观点来看,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. 剑指offer编程题Java实现——面试题5从头到尾打印链表

    题目描述* 剑指offer面试题5:从尾到头打印链表 输入一个链表的头结点,从尾到头打印出每个结点的值 解决方案一:首先遍历链表的节点后打印,典型的"后进先出",可以使用栈来实现这 ...

  2. java(jdk1.7) IO系列01之InputStream和OutputStream解析

    1.InputStream和OutputStream简介 在java中InputStream和OutputStream分别代表字节输入流和字节输出流,表示以字节的方式来实现进程或者程序的通信,Inpu ...

  3. 读书笔记 effective c++ Item 10 让赋值运算符返回指向*this的引用

    一个关于赋值的有趣的事情是你可以将它们链在一起: int x, y, z; x = y = z = ; // chain of assignments 同样有趣的是赋值采用右结合律,所以上面的赋值链被 ...

  4. 阿里宣布Atlas正式开源:带你重返App开发的田园时代

    继Weex之后,阿里在移动技术领域又有开源大动作. 3月13日,手机淘宝安卓客户端容器化框架Atlas正式宣布开源(https://github.com/alibaba/atlas ).Atlas由阿 ...

  5. Java设计模式之职责型模式总结

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6548127.html 所谓职责型模式,就是采用各种模式来分配各个类的职责. 职责型模式包括 ...

  6. SQL一次查出相关类容避免长时间占用表(下)

    /* server: db: EDI */ -- 以下案例多次查询同一张表,仅有Name条件不同 --可以使用一次查出相关类容避免长时间占用表 USE EDI GO DECLARE @FileType ...

  7. JDBC-Eclipse & Mysql & Servlet实现

    import java.io.IOException;import java.io.PrintWriter;import java.sql.Connection;import java.sql.Dri ...

  8. 手机端rem如何适配_rem详解及使用方法

    什么是rem 在我看来,rem就是1rem单位就等于html节点fontsize的像素值.所以改变html节点的fontsize是最为关键的一步.根据手机宽度改变相对大小就可以实现自适应了,就不用什么 ...

  9. 详解< meta http-equiv = "X-UA-Compatible" content = "IE=edge,chrome=1" />

    < meta http-equiv = "X-UA-Compatible" content = "IE=edge,chrome=1" /> 这是个是 ...

  10. IE10去掉input的type=”text”输入内容时出现的小叉号(X)和type=”password”出现的小眼睛图标

    最近在做一个后台管理系统项目,遇到以下两个问题: 1.从IE 10开始,type="text" 的 input 在用户输入内容后,会自动产生一个小叉号(X),方便用户点击清除已经输 ...