基本概念

  在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意一个对象,能否调用它的任意一个方法?

  答案是肯定的。

  这种动态获取类的信息以及动态调用对象的方法的功能来自于Java语言的反射(Reflection)机制

  

  Java反射机制主要提供了以下功能:

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

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

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

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

  Reflection是Java被视为动态(或准动态)语言的一个关键性质。

  这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息。

  包括其modifiers(诸如public、static等)、 superclass(例如Object)、实现了的 interfaces (例如Serializable)、也包括其fields和methods的所有信息,并可于运行时改变fields内容或调用methods。

动态语言

  动态语言的定义“程序运行时,允许改变程序结构或者变量类型,这种语言称为动态语言”。

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

  尽管在这样的定义与分类下Java不是动态语言,它却有着一个非常突出的动态相关机制:Reflection。这个字的意思是:反射、映像、倒影,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。

  换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。

  这种“看透”class的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflectionintrospection是常被并提的两个术语。

Java Reflection API简介

  在JDK中,主要由以下类来实现Java反射机制,这些类(除了第一个)都位于java.lang.reflect包中

  Class类:代表一个类,位于java.lang包下。

  Field类:代表类的成员变量(成员变量也称为类的属性)。

  Method类:代表类的方法。

  Constructor类:代表类的构造方法。

  Array类:提供了动态创建数组,以及访问数组的元素的静态方法。

Class对象

  要想使用反射,首先需要获得待操作的类所对应的Class对象。

  Java中,无论生成某个类的多少个对象,这些对象都会对应于同一个Class对象。

  这个Class对象是由JVM生成的,通过它能够获悉整个类的结构。

常用的获取Class对象的3种方式:

  1.使用Class类的静态方法。例如:  

Class.forName("java.lang.String");

  2.使用类的.class语法。如:

String.class;

  3.使用对象的getClass()方法。如:

String str = "aa";
Class<?> classType1 = str.getClass();

  getClass()方法定义在Object类中,不是静态方法,需要通过对象来调用,并且它声明为final,表明不能被子类所覆写。

  直接print所获得的Class对象classType会输出:

    class 完整类名

  如果调用该Class对象的getName()方法,则输出完整类名,不加class。

例程1:获取方法

  例程ReflexTest 类演示了Reflection API的基本作用,它读取命令行参数指定的类名,然后打印这个类所具有的方法信息。 

package com.reflex;

import java.lang.reflect.Field;
import java.lang.reflect.Method; public class ReflexTest { public static void main(String[] args) {
try {
Class c = Class.forName("java.lang.Integer");
Field[] fs = c.getDeclaredFields(); for(Field f:fs){
System.out.println(f);
}
System.out.println("==================================================");
Method[] methods = c.getDeclaredMethods();
for(Method method:methods){
System.out.println(method);
} } catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

结果:

public static final int java.lang.Integer.MIN_VALUE
public static final int java.lang.Integer.MAX_VALUE
public static final java.lang.Class java.lang.Integer.TYPE
static final char[] java.lang.Integer.digits
static final char[] java.lang.Integer.DigitTens
static final char[] java.lang.Integer.DigitOnes
static final int[] java.lang.Integer.sizeTable
private final int java.lang.Integer.value
public static final int java.lang.Integer.SIZE
private static final long java.lang.Integer.serialVersionUID
static final boolean java.lang.Integer.$assertionsDisabled
==================================================
public int java.lang.Integer.hashCode()
public boolean java.lang.Integer.equals(java.lang.Object)
public static java.lang.String java.lang.Integer.toString(int,int)
public java.lang.String java.lang.Integer.toString()
public static java.lang.String java.lang.Integer.toString(int)
public static java.lang.String java.lang.Integer.toHexString(int)
public static int java.lang.Integer.compare(int,int)
public int java.lang.Integer.compareTo(java.lang.Object)
public int java.lang.Integer.compareTo(java.lang.Integer)
public static java.lang.Integer java.lang.Integer.decode(java.lang.String) throws java.lang.NumberFormatException
static void java.lang.Integer.getChars(int,int,char[])
public static java.lang.Integer java.lang.Integer.valueOf(int)
public static java.lang.Integer java.lang.Integer.valueOf(java.lang.String,int) throws java.lang.NumberFormatException
public static java.lang.Integer java.lang.Integer.valueOf(java.lang.String) throws java.lang.NumberFormatException
public long java.lang.Integer.longValue()
public int java.lang.Integer.intValue()
public static int java.lang.Integer.reverse(int)
static int java.lang.Integer.stringSize(int)
public static int java.lang.Integer.reverseBytes(int)
public byte java.lang.Integer.byteValue()
public double java.lang.Integer.doubleValue()
public float java.lang.Integer.floatValue()
public short java.lang.Integer.shortValue()
public static int java.lang.Integer.parseInt(java.lang.String) throws java.lang.NumberFormatException
public static int java.lang.Integer.parseInt(java.lang.String,int) throws java.lang.NumberFormatException
public static int java.lang.Integer.bitCount(int)
public static java.lang.Integer java.lang.Integer.getInteger(java.lang.String,int)
public static java.lang.Integer java.lang.Integer.getInteger(java.lang.String)
public static java.lang.Integer java.lang.Integer.getInteger(java.lang.String,java.lang.Integer)
public static int java.lang.Integer.highestOneBit(int)
public static int java.lang.Integer.lowestOneBit(int)
public static int java.lang.Integer.numberOfLeadingZeros(int)
public static int java.lang.Integer.numberOfTrailingZeros(int)
public static int java.lang.Integer.rotateLeft(int,int)
public static int java.lang.Integer.rotateRight(int,int)
public static int java.lang.Integer.signum(int)
public static java.lang.String java.lang.Integer.toBinaryString(int)
public static java.lang.String java.lang.Integer.toOctalString(int)
private static java.lang.String java.lang.Integer.toUnsignedString(int,int)

例程2:通过反射调用方法

  通过反射调用方法。详情见代码及注释:

package com.reflex;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; public class InvokeTester { public int add(int param1, int param2) {
return param1 + param2;
} public String echo(String message) {
return "Hello: " + message;
} public static void main(String[] args)
throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
// 以前的常规执行手段
InvokeTester tester = new InvokeTester();
System.out.println(tester.add(1, 2));
System.out.println(tester.echo("Tom"));
System.out.println("---------------------------"); // 通过反射的方式
// 第一步,获取Class对象
// 前面用的方法是:Class.forName()方法获取
// 这里用第二种方法,类名.class
Class<?> classType = InvokeTester.class;
Object invokeTester = classType.newInstance();
System.out.println(invokeTester instanceof InvokeTester);// 输出true // 通过反射调用方法
// 首先需要获得与该方法对应的Method对象
// 第一个参数是方法名,第二个参数是这个方法所需要的参数的Class对象的数组
Method addMethd = classType.getMethod("add", new Class[] { int.class, int.class });
// 调用目标方法
Object addResult = addMethd.invoke(invokeTester,new Object[]{1,2});
System.out.println(addResult); //调用第二个echo方法
Method echoMethod = classType.getMethod("echo", new Class[] {String.class});
Object echoResult = echoMethod.invoke(invokeTester,new Object[]{"tom"});
System.out.println(echoResult);
}
}

生成对象

  若想通过类的不带参数的构造方法来生成对象,我们有两种方式:

  1.先获得Class对象,然后通过该Class对象的newInstance()方法直接生成即可:

2.先获得Class对象,然后通过该对象获得对应的Constructor对象,再通过该Constructor对象的newInstance()方法生成

  (其中Customer是一个自定义的类,有一个无参数的构造方法,也有带参数的构造方法):
    Class<?> classType = String.class;

     Object obj = classType.newInstance();
Class<?> classType = Customer.class;

    // 获得Constructor对象,此处获取第一个无参数的构造方法的
Constructor cons = classType.getConstructor(new Class[] {}); // 通过构造方法来生成一个对象
Object obj = cons.newInstance(new Object[] {});

若想通过类的带参数的构造方法生成对象,只能使用下面这一种方式:

  (Customer为一个自定义的类,有无参数的构造方法,也有一个带参数的构造方法,传入字符串和整型)

    Class<?> classType = Customer.class;

    Constructor cons2 = classType.getConstructor(new Class[] {String.class, int.class});

    Object obj2 = cons2.newInstance(new Object[] {"ZhangSan",20});

11.Java反射机制 哦对了,前面的序号来自随笔关于编程之路的思索第一篇的更多相关文章

  1. 11 java 反射机制

    Java反射机制的适用场景及其利与弊: http://blog.csdn.net/zolalad/article/details/29370565 http://my.oschina.net/u/10 ...

  2. 第28章 java反射机制

    java反射机制 1.类加载机制 1.1.jvm和类 运行Java程序:java 带有main方法的类名 之后java会启动jvm,并加载字节码(字节码就是一个类在内存空间的状态) 当调用java命令 ...

  3. java基础知识(十一)java反射机制(上)

    java.lang.Class类详解 java Class类详解 一.class类 Class类是java语言定义的特定类的实现,在java中每个类都有一个相应的Class对象,以便java程序运行时 ...

  4. java反射机制深入详解

    java反射机制深入详解  转自:http://www.cnblogs.com/hxsyl/archive/2013/03/23/2977593.html 一.概念 反射就是把Java的各种成分映射成 ...

  5. [转]java反射机制

    原文地址:http://www.cnblogs.com/jqyp/archive/2012/03/29/2423112.html 一.什么是反射机制         简单的来说,反射机制指的是程序在运 ...

  6. Java反射机制详解

    Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反 ...

  7. Java反射机制(Reflection)

    Java反射机制(Reflection) 一.反射机制是什么 Java反射机制是程序在运行过程中,对于任意一个类都能够知道这个类的所有属性和方法;对于任意一个对象都能够调用它的任意一个方法和属性,这种 ...

  8. JAVA反射机制学�

    JAVA反射机制:对于随意一个类,都可以知道这个类的全部属性和方法:对于随意一个对象,都可以调用它的随意一个方法和属性:这样的动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. J ...

  9. Java 反射机制浅析

    Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反 ...

随机推荐

  1. windows SVN搭建

    Subversion是优秀的版本控制工具,其具体的的优点和详细介绍,这里就不再多说. 首先来下载和搭建SVN服务器. 现在Subversion已经迁移到apache网站上了,下载地址: http:// ...

  2. 导入maven工程并配置maven环境

    步骤一 : 选择 "Import"操作 有两个途径可以选择 "Import"操作; 1>"File"--> "Impo ...

  3. ORACLE十进制与十六进制的转换

    十进制与十六进制的转换 十进制-->十六进制 select to_char(100,'XX') from dual; 十六进制-->十进制select to_number('7D','XX ...

  4. vsUnit单元测试

    在自定义的方法名上[右键]然后选择[创建单元测试],之后在项目中就添加了一个单元测试的项目,找到对应的单元测试的方法[TestMethod()]特性修饰,将单元测试的方法中最后一句:Assert.In ...

  5. ELK-Python(三)

    不具有通用性,留作纪念. [root@GXB-CTRLCENTER python]# cat insert_uv.py #!/usr/bin/env python # -*- coding:utf-8 ...

  6. OpenGl的glMatrixMode()函数理解

    glMatrixMode()函数的参数,这个函数其实就是对接下来要做什么进行一下声明,也就是在要做下一步之前告诉计算机我要对“什么”进行操作了,这个“什么”在glMatrixMode的“()”里的选项 ...

  7. kernel 模块与简单 hello 模块

    Kernel 模块与简单 hello 模块 kernel 模块的简介 Linux 内核进行扩展时,例如编写驱动程序.netfilter功能等,最方便的方式是通过编写模块,然后加载到内核中.由于 ker ...

  8. Android开源项目SlidingMenu深入剖析

    SlidingMenu简介: SlidingMenu的是一种比较新的设置界面或配置界面效果,在主界面左滑或者右滑出现设置界面,能方便的进行各种操作.目前有大量的应用都在使用这一效果.如Evernote ...

  9. 第七篇 Integration Services:中级工作流管理

    本篇文章是Integration Services系列的第七篇,详细内容请参考原文. 简介在上一篇文章,我们创建了一个新的SSIS包,学习了SSIS中的脚本任务和优先约束,并检查包的MaxConcur ...

  10. WW多线程和锁

    问题: WorldWind中是双线程的,一直忽略了多线程中数据共享,修改数据会产生问题.可是在WW中并没有看到锁的东西. 还有就是动态释放内存的问题.因为采用D3D的C#封装库不可避免涉及COM对象的 ...