Java 反射练习
已同步更新至个人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 反射练习的更多相关文章
- 第28章 java反射机制
java反射机制 1.类加载机制 1.1.jvm和类 运行Java程序:java 带有main方法的类名 之后java会启动jvm,并加载字节码(字节码就是一个类在内存空间的状态) 当调用java命令 ...
- Java反射机制
Java反射机制 一:什么事反射机制 简单地说,就是程序运行时能够通过反射的到类的所有信息,只需要获得类名,方法名,属性名. 二:为什么要用反射: 静态编译:在编译时确定类型,绑定对象,即通过 ...
- java反射(基础了解)
package cn.itcast_01; /** *Person类 */ public class Person { /** 姓名 */ private String name; ...
- java基础知识(十一)java反射机制(上)
java.lang.Class类详解 java Class类详解 一.class类 Class类是java语言定义的特定类的实现,在java中每个类都有一个相应的Class对象,以便java程序运行时 ...
- java基础知识(十一)java反射机制(下)
1.什么是反射机制? java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用他的属性和方法,这种动态获取属性和方法的功能称为java的反射机制. ...
- java反射学习之二万能EXCEL导出
一.EXCEL导出的实现过程 假设有一个对象的集合,现在需要将此集合内的所有对象导出到EXCEL中,对象有N个属性:那么我们实现的方式是这样的: 循环这个集合,在循环集合中某个对象的所有属性,将这个对 ...
- java反射学习之一反射机制概述
一.反射机制背景概述 1.反射(reflection)是java被视为动态语言的一个关键性质 2.反射机制指的是程序在运行时能获取任何类的内部所有信息 二.反射机制实现功能概述 1.只要给定类的全名, ...
- java反射 之 反射基础
一.反射 反射:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为 ...
- java反射 cglib asm相关资料
有篇文章对java反射的调用的效率做了测试,写的比较好.猛击下面地址 http://www.blogjava.net/stone2083/archive/2010/09/15/332065.html ...
- 超详细的java反射教程
看技术博客时,看到关于java反射的博文,写的非常好.猛击下面的地址,开始java反射之旅 中文翻译地址:http://ifeve.com/java-reflection/ 英文原版地址:http:/ ...
随机推荐
- DBHelp数据处理类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- (原创)基于MCU的频率可调,占空比可调的PWM实现(MCU,MCS-51/MSP430)
1.Abstract 做这个是受朋友之邀,用在控制电机转动的方面.他刚好在一家好的单位实习,手头工作比较多,无暇分身,所以找我帮忙做个模型.要求很明晰,PWM的频率在0~1KHz范围内,占空比 ...
- C/C++中static关键字详解
静态变量作用范围在一个文件内,程序开始时分配空间,结束时释放空间,默认初始化为0,使用时可以改变其值. 静态变量或静态函数只有本文件内的代码才能访问它,它的名字在其它文件中不可见.用法1:函数内部声明 ...
- Wordnet的一些简单使用
转载请说明出处:http://www.cnblogs.com/KingKou/p/4121373.html 1.简介 Wordnet是一个由普林斯顿大学认识科学实验室在心理学教授乔治·A·米勒的指导下 ...
- Magicodes.WeiChat——WeChatOAuthTest(网页授权获取用户基本信息)
Demo访问地址:http://wechat.magicodes.net/app/AppDemo/WeChatOAuthTest?tenantId=1 关于公众号如何获取用户信息,请参考此文档:htt ...
- 阿里云中Centos下配置防火墙
一.检查iptables服务状态 [root@woxplife ~]# service iptables status iptables: Firewall is not running. 说明ipt ...
- VS下的Resharper插件报错“Can not resolve symbol”的解决办法
今天准备写代码的时候,发现代码中大片的红色,就像下面的图片一样.但是编译一下,也可以重新生成,运行也没有问题.于是就看了下svn上是不是有人改了哪里,发现也没有问题.于是又清理了下解决方案,再次生成, ...
- 读《你必须知道的.NET》继承本质论 Bird bird=new Chicken()
我们创建如下的三层继承层次类. public abstract class Animal { public abstract void ShowType(); } public class Bird ...
- Atitit .html5刮刮卡的gui实现总结
Atitit .html5刮刮卡的gui实现总结 #----两个案例canvas或者wScratchPad-1.4.4 1 #----1.添加panel ,这个十mask div.....posti ...
- paip.gui控件form窗体的原理实现以及easyui的新建以及编辑实现
paip.gui控件form窗体的原理实现以及easyui的新建以及编辑实现 //////新建 与编辑 var EditForm=new Form_easyui(); if(row) ...