已同步更新至个人blog:http://dxjia.cn/2015/08/java-reflect/

  引用baidubaike上对JAVA反射的说明,如下:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法(成员变量和函数);对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

而能够使JAVA有这样的能力,归根结底是由于JVM,而小一点说,是因为有Class对象的存在,我在上一篇文章中有讲解JAVA的Class对象,它是在类加载完后,每个类都会产生的一个实例,而其内部详细描述了这个类的情况,所以我们可以通过这个Class对象来得到任何有关这个类的细节,不仅仅能了解这个类,java还提供了方法来动态执行这个类里的方法或修改成员变量的值。

反射机制的优点与缺点:(参考:【Java反射机制】)

为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念,
  静态编译:在编译时确定类型,绑定对象,即通过。
  动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。
  一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中它的灵活性就表现的十分明显。比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个程序编
译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能
的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功 能。
  它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。

下面是我的练习程序:

在目录下新建com\dxjia\sample路径,然后在sample下新建一个UserBean.java的文件,这将是我们用来进行反射的类。代码如下:

 package com.dxjia.sample;

 public class UserBean {
private String mName;
private int mAge;
private String mVersion = "1.0"; public UserBean() {
System.out.println(" UserBean Constructor1 called!");
} public UserBean(String name, int age) {
System.out.println(" UserBean Constructor2 called!");
init(name, age);
} public void setName(String name) {
mName = name;
System.out.println(" UserBean setName() done");
} public String getName() {
return mName;
} public void setAge(int age) {
mAge = age;
System.out.println(" UserBean setAge() done");
} public int getAge() {
return mAge;
} private void init(String name, int age) {
mName = name;
mAge = age;
} public void printVersion() {
System.out.println(" UserBean VERSION: " + mVersion);
} public void printName() {
System.out.println(" UserBean mName [" + mName + "]");
} public void printAge() {
System.out.println(" UserBean mAge [" + mAge + "]");
} private void printUserInfo() {
System.out.println(" UserBean mName [" + mName + "] " + "mAge [" + mAge + "]");
}
}

然后在根目录下新建Test.java文件,这里实现我们的测试程序,代码如下【注意注释】:

 import java.lang.*;
import java.lang.reflect.*; public class Test { public static void main(String[] args) { try {
Class c = Class.forName("com.dxjia.sample.UserBean");
if (null == c) {
System.out.println("can`t load class!");
return;
} System.out.println("\n--------------获取类的所有信息----------------------\n"); // 获取类的修饰符,public private...
int mod = c.getModifiers();
String modifier = Modifier.toString(mod);
System.out.println("modifier : " + modifier); // 获取父类
Class superClass = c.getSuperclass();
String superClassName = superClass.getName();
System.out.println("superClassName : " + superClassName); // 获取implements的接口
Class[] interfaces = c.getInterfaces();
if (interfaces.length != 0) {
for (Class cl : interfaces) {
System.out.println("interfacesName : " + cl.getName());
}
} else {
System.out.println("interfacesName : ");
} // 获取所有的成员变量
Field[] fields = c.getDeclaredFields();
if (fields.length != 0) {
System.out.println("fields : ");
for (Field field : fields) {
modifier = Modifier.toString(field.getModifiers());
Class type = field.getType();
String name = field.getName();
if (type.isArray()) {
String arrType = type.getComponentType().getName() + "[]";
System.out.println(" " + modifier + " " + arrType + " " + name + ";");
} else {
System.out.println(" " + modifier + " " + type + " " + name + ";");
}
}
} else {
System.out.println("fields : ");
} // 获取所有的构造函数
Constructor[] constructors = c.getDeclaredConstructors();
if(constructors.length != 0) {
System.out.println("constructors : ");
for (Constructor constructor : constructors) {
// 构造方法名
String name = constructor.getName();
// 获取访问修饰符,public private protected
modifier = Modifier.toString(constructor.getModifiers());
System.out.print(" " + modifier +" " + name + "(");
// 获取构造方法中的所有参数, paramTypes.length为0,说明是无参构造函数
Class[] paramTypes = constructor.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
if (i > 0) {
System.out.print(", ");
}
if (paramTypes[i].isArray()) {
System.out.print(paramTypes[i].getComponentType().getName()+"[]");
} else {
System.out.print(paramTypes[i].getName());
}
}
System.out.print(")\n");
}
} else {
System.out.println("constructors : ");
} // 获取所有的成员函数
Method[] methods = c.getDeclaredMethods();
if(methods.length != 0) {
System.out.println("methods : ");
for (Method method: methods) {
// 获取方法的描述符,private public protected...
modifier = Modifier.toString(method.getModifiers());
// 获取方法的返回类型
Class returnType = method.getReturnType();
if (returnType.isArray()) {
String arrType = returnType.getComponentType().getName()+"[]";
System.out.print(" " + modifier + " " + arrType + " " + method.getName() + "(");
} else {
System.out.print(" " + modifier + " " + returnType.getName() + " " + method.getName() + "(");
}
// 获取所有的参数信息
Class[] paramTypes = method.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
if (i > 0) {
System.out.print(",");
}
if (paramTypes[i].isArray()) {
System.out.println(paramTypes[i].getComponentType().getName()+"[]");
} else {
System.out.print(paramTypes[i].getName());
}
}
System.out.println(");");
}
} else {
System.out.println("methods : ");
} System.out.println("\n----------------测试使用----------------------\n"); /**
* 测试反射,调用函数,变量赋值等
* 反射的使用一般都会先像上面这样打印出来,进行一个分析之后,
* 再编写类似下面的代码来反射调用类的函数,也就是自己先通过上面的方式来了解这个类,
* 然后再hard code反射使用这个类中对自己有用的函数来达到目的。当然,我们比较了解那个类了,只是环境中没有公开,所以我们需要反射
*/
// 首先可以实例化对象,因为万物都继承自Object
// 所以这里用Object来声明定义对象,不影响使用
// 直接使用Class.newInstance()函数,是调用的类的无参构造函数
System.out.println("调用无参构造函数");
Object bean1 = c.newInstance(); // 如果要调用有参构造函数,那就要使用下面的方式
Class[] paramTypes = {String.class, int.class};
Constructor con = c.getConstructor(String.class, int.class);
// 使用
System.out.println("调用有参构造函数");
Object bean2 = con.newInstance("小明", 16); // 调用bean2 public 函数 printVersion()
System.out.println("执行public printVersion()");
Method method1 = c.getDeclaredMethod("printVersion");
method1.invoke(bean2); // 调用bean2 private函数 printUserInfo()
System.out.println("执行public printUserInfo()");
Method method2 = c.getDeclaredMethod("printUserInfo");
// 因为printUserInfo是private方法,所以需要加上这句来避免安全检查,这样才可以调用私有方法
method2.setAccessible(true);
// 执行
method2.invoke(bean2); // 调用有参数的函数 setName() setAge()
System.out.println("调用有参数函数设置新name和age");
Method method3 = c.getDeclaredMethod("setName", String.class);
method3.invoke(bean2, "张三");
Method method4 = c.getDeclaredMethod("setAge", int.class);
method4.invoke(bean2, 25); // 调用 printUserInfo 将新值打印出来
System.out.println("打印新值");
method2.invoke(bean2); // 直接操作成员变量,给私有成员变量赋值,记得加setAccessible(true);
Field field = c.getDeclaredField("mVersion");
field.setAccessible(true);
String oldVersion = (String) field.get(bean2);
System.out.println("直接获取私有变量mVersion的值,并打印:" + oldVersion);
System.out.println("直接将私有成员变量mVersion赋值2.0");
field.set(bean2, "2.0");
// 调用printVersion()打印新值
System.out.println("打印新值");
method1.invoke(bean2);
} catch (ClassNotFoundException e) {
System.out.println("exception: " + e.toString());
} catch (InstantiationException e) {
System.out.println("exception: " + e.toString());
} catch (IllegalAccessException e) {
System.out.println("exception: " + e.toString());
} catch (NoSuchMethodException e) {
System.out.println("exception: " + e.toString());
} catch (InvocationTargetException e) {
System.out.println("exception: " + e.toString());
} catch (NoSuchFieldException e) {
System.out.println("exception: " + e.toString());
}
} }

打开cmd,切换到该目录下,执行

 javac com\dxjia\sample\UserBean.java
javac -encoding UTF-8 -Xlint:unchecked Test.java

编译通过后,执行:

 java Test

打印如下:

--------------获取类的所有信息----------------------

modifier       : public
superClassName : java.lang.Object
interfacesName :
fields :
private class java.lang.String mName;
private int mAge;
private class java.lang.String mVersion;
constructors :
public com.dxjia.sample.UserBean()
public com.dxjia.sample.UserBean(java.lang.String, int)
methods :
public int getAge();
public void printName();
public void printAge();
public java.lang.String getName();
private void init(java.lang.String,int);
public void setName(java.lang.String);
public void setAge(int);
public void printVersion();
private void printUserInfo(); ----------------测试使用---------------------- 调用无参构造函数
UserBean Constructor1 called!
调用有参构造函数
UserBean Constructor2 called!
执行public printVersion()
UserBean VERSION: 1.0
执行public printUserInfo()
UserBean mName [小明] mAge [16]
调用有参数函数设置新name和age
UserBean setName() done
UserBean setAge() done
打印新值
UserBean mName [张三] mAge [25]
直接获取私有变量mVersion的值,并打印:1.0
直接将私有成员变量mVersion赋值2.0
打印新值
UserBean VERSION: 2.0

Java 反射练习的更多相关文章

  1. 第28章 java反射机制

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

  2. Java反射机制

    Java反射机制 一:什么事反射机制 简单地说,就是程序运行时能够通过反射的到类的所有信息,只需要获得类名,方法名,属性名. 二:为什么要用反射:     静态编译:在编译时确定类型,绑定对象,即通过 ...

  3. java反射(基础了解)

    package cn.itcast_01; /** *Person类 */ public class Person {    /** 姓名 */    private String name;     ...

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

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

  5. java基础知识(十一)java反射机制(下)

    1.什么是反射机制? java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用他的属性和方法,这种动态获取属性和方法的功能称为java的反射机制. ...

  6. java反射学习之二万能EXCEL导出

    一.EXCEL导出的实现过程 假设有一个对象的集合,现在需要将此集合内的所有对象导出到EXCEL中,对象有N个属性:那么我们实现的方式是这样的: 循环这个集合,在循环集合中某个对象的所有属性,将这个对 ...

  7. java反射学习之一反射机制概述

    一.反射机制背景概述 1.反射(reflection)是java被视为动态语言的一个关键性质 2.反射机制指的是程序在运行时能获取任何类的内部所有信息 二.反射机制实现功能概述 1.只要给定类的全名, ...

  8. java反射 之 反射基础

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

  9. java反射 cglib asm相关资料

    有篇文章对java反射的调用的效率做了测试,写的比较好.猛击下面地址 http://www.blogjava.net/stone2083/archive/2010/09/15/332065.html ...

  10. 超详细的java反射教程

    看技术博客时,看到关于java反射的博文,写的非常好.猛击下面的地址,开始java反射之旅 中文翻译地址:http://ifeve.com/java-reflection/ 英文原版地址:http:/ ...

随机推荐

  1. 不可变String

    1,什么是不可变String? String对象是不可变的.当试图修改String值的时候,实际上都是创建一个全新的String对象,该对象包含修改后字符串的值,而最初的对象则没有发生改变. pack ...

  2. [2013 Final] Colors

    Description Ziyao has a big drawing board with N * M squares. At the beginning, all the squares on t ...

  3. C#设计模式——抽象工厂

    一.引言 我相信看到这段文字的人,都具备了良好的技术功底.但是对于自己编写的代码总是充满抱怨,希望能够将自己编写的代码如同房子一般先进行有效 的设计,然后在进行建设.那么这篇文章能够给你一些思路,这里 ...

  4. SQL Server 导入大数据脚本

    .先使用win+r运行cmd .执行osql -S DESKTOP-RGBEDS3 -U sa -P liyang -d FGCPOE_十院 -i D:\数据库\script.sql 即可!

  5. 基于OWIN WebAPI 使用OAUTH2授权服务【授权码模式(Authorization Code)】

    之前已经简单实现了OAUTH2的授权码模式(Authorization Code),但是基于JAVA的,今天花了点时间调试了OWIN的实现,基本就把基于OWIN的OAUHT2的四种模式实现完了.官方推 ...

  6. windowsXP用户被禁用导致不能网站登录

    1.查看系统事件,发现弹出如下的错误 2.根据上面的错误,我们很容易就可以判断是禁用了账户引起的 2.1后面进入计算机管理,再进入用户管理 2.2双击点开Internet来宾用于,发现此用户已经停用了 ...

  7. php后台开发(一)hello world

    php后台开发(一)hello world 环境安装 开发环境为Ubuntu 12.04,选择linux+apache+php的开发环境 安装 apache2 sudo apt-get install ...

  8. servlet+jsp+java实现Web 应用

    servlet+jsp+java实现Web 应用 用java来构建一个web应用是特别容易的事情,jsp和php很像,可以嵌套在html中.程序的结构很简单,也很清楚,本文主要记录下大概的开发过程和环 ...

  9. Atitit. 解压缩zip文件 的实现最佳实践 java c# .net php

    Atitit. 解压缩zip文件 的实现最佳实践 java c# .net php 1. Jdk zip 跟apache ant zip 1 2. Apache Ant包进行ZIP文件压缩,upzip ...

  10. ecshop2.72文件结构说明

    ECShop 2.7.2 的结构图及各文件相应功能介绍 ECShop 2.7.2 upload 的目录┣ activity.php 活动列表┣ affiche.php 广告处理文件┣ affiliat ...