Java反射机制(二):通过反射取得类的结构
在反射运用过程中,如果你想得到一个类的完整结构,那么就要使用到java.lang.reflect包中的几个类:
· Constructor 表示类中的构造方法
· Field 表示类中的属性
· Method 表示类中的方法
接下来,我们讲讲,如何通过这些API,去获取一个类的完整性结构。
首先,我们定义一个类:
package com.chen.yuan.vo;
interface China{ // 定义China接口
public static final String NATIONAL = "China" ; // 定义全局常量
public static final String AUTHOR = "李兴华" ; // 定义全局常量
public void sayChina() ; // 无参的,没有返回值的方法
public String sayHello(String name,int age) ; // 定义有两个参数的方法,并返回内容
}
public class Person implements China{
private String name ;
private int age ;
public Person(){ // 无参构造
}
public Person(String name){
this.name = name ; // 设置name属性
}
public Person(String name,int age){
this(name) ;
this.age = age ;
}
public void sayChina(){ // 覆写方法
System.out.println("作者:" + AUTHOR + ",国籍:" + NATIONAL) ;
}
public String sayHello(String name,int age){
return name + ",你好!我今年:" + age + "岁了!" ;
}
public void setName(String name){
this.name = name ;
}
public void setAge(int age){
this.age = age ;
}
public String getName(){
return this.name ;
}
public int getAge(){
return this.age ;
}
};
一、 通过反射取得类所实现的全部接口
package com.chen.yuan.vo;
public class GetInterfaceDemo{
public static void main(String args[]){
Class<?> c1 = null ; // 声明Class对象
try{
c1 = Class.forName("com.chen.yuan.vo.Person") ; // 实例化对象
}catch(ClassNotFoundException e){
e.printStackTrace() ;
}
Class<?> c[] = c1.getInterfaces() ; // 以数组形式返回实现的全部接口
for(int i=0;i<c.length;i++){
System.out.println("实现的接口名称:" + c[i].getName()) ; // 输出接口名称
}
}
};
输出: 实现的接口名称:com.chen.yuan.vo.China
二、 取得类所继承的父类
package com.chen.yuan.vo;
public class GetSuperClassDemo{
public static void main(String args[]){
Class<?> c1 = null ; // 声明Class对象
try{
c1 = Class.forName("com.chen.yuan.vo.Person") ; // 实例化对象
}catch(ClassNotFoundException e){
e.printStackTrace() ;
}
Class<?> c2 = c1.getSuperclass() ; // 取得父类
System.out.println("父类名称:" + c2.getName()) ;
}
};
输出: 父类名称:java.lang.Object
三、取得类中的全部构造方法
public class GetConstructorDemo01{
public static void main(String args[]){
Class<?> c1 = null ; // 声明Class对象
try{
c1 = Class.forName("com.chen.yuan.vo.Person") ; // 实例化对象
}catch(ClassNotFoundException e){
e.printStackTrace() ;
}
Constructor<?> con[] = c1.getConstructors() ; // 取得一个类中的全部构造
for(int i=0;i<con.length;i++){
System.out.println("构造方法:" + con[i]) ; // 输出构造,直接打印
}
}
};
输出:
构造方法:public com.chen.yuan.vo.Person(java.lang.String,int)
构造方法:public com.chen.yuan.vo.Person(java.lang.String)
构造方法:public com.chen.yuan.vo.Person()
以上直接打印出构造方法,调用的是Constructor类中 的toString()方法。
Constructor类中存在了一下几个几个方法:
· public int getModifiers()取得修饰符
· public String getName()取得方法名称
· public Class<?>[] getParameterTypes()取得参数的类型
public class GetConstructorDemo02{
public static void main(String args[]){
Class<?> c1 = null ; // 声明Class对象
try{
c1 = Class.forName("com.chen.yuan.vo.Person") ; // 实例化对象
}catch(ClassNotFoundException e){
e.printStackTrace() ;
}
Constructor<?> con[] = c1.getConstructors() ; // 取得一个类中的全部构造
for(int i=0;i<con.length;i++){
Class<?> p[] = con[i].getParameterTypes() ; // 得到构造方法中的全部参数
System.out.print("构造方法:" ) ; // 输出构造,直接打印
System.out.print(con[i].getModifiers() + " ") ; // 得到修饰符
System.out.print(con[i].getName()) ; // 取得构造方法的名字
System.out.print("(") ;
for(int j=0;j<p.length;j++){
System.out.print(p[j].getName() + " arg" + i) ;
if(j<p.length-1){
// 判断此是否是最后一个参数
System.out.print(","); // 输出“,”
}
}
System.out.println("){}") ;
}
}
};
输出:
构造方法:1 com.chen.yuan.vo.Person(java.lang.String arg0,int arg0){}
构造方法:1 com.chen.yuan.vo.Person(java.lang.String arg1){}
构造方法:1 com.chen.yuan.vo.Person(){}
观察输出,我们发现,所有的修饰符变成了数字,我们肯定不懂这些个数字是什么意思,那么接下来,让我们还原修饰符。此时,我们需要借助Modifier类完成,此类定义在java.lang.reflect包中,我们可以直接使用Modifier类中的toString(int mod)方法完成还原修饰符的操作。
先看一下Modifier类中的toString(int mod)方法的源码:
/**
* The {@code int} value representing the {@code public}
* modifier.
*/
public static final int PUBLIC = 0x00000001; /**
* The {@code int} value representing the {@code private}
* modifier.
*/
public static final int PRIVATE = 0x00000002; /**
* The {@code int} value representing the {@code protected}
* modifier.
*/
public static final int PROTECTED = 0x00000004; /**
* The {@code int} value representing the {@code static}
* modifier.
*/
public static final int STATIC = 0x00000008; /**
* The {@code int} value representing the {@code final}
* modifier.
*/
public static final int FINAL = 0x00000010; /**
* The {@code int} value representing the {@code synchronized}
* modifier.
*/
public static final int SYNCHRONIZED = 0x00000020; /**
* The {@code int} value representing the {@code volatile}
* modifier.
*/
public static final int VOLATILE = 0x00000040; /**
* The {@code int} value representing the {@code transient}
* modifier.
*/
public static final int TRANSIENT = 0x00000080; /**
* The {@code int} value representing the {@code native}
* modifier.
*/
public static final int NATIVE = 0x00000100; /**
* The {@code int} value representing the {@code interface}
* modifier.
*/
public static final int INTERFACE = 0x00000200;
public static String toString(int mod) {
StringBuffer sb = new StringBuffer();
int len;
if ((mod & PUBLIC) != 0) sb.append("public ");
if ((mod & PROTECTED) != 0) sb.append("protected ");
if ((mod & PRIVATE) != 0) sb.append("private ");
/* Canonical order */
if ((mod & ABSTRACT) != 0) sb.append("abstract ");
if ((mod & STATIC) != 0) sb.append("static ");
if ((mod & FINAL) != 0) sb.append("final ");
if ((mod & TRANSIENT) != 0) sb.append("transient ");
if ((mod & VOLATILE) != 0) sb.append("volatile ");
if ((mod & SYNCHRONIZED) != 0) sb.append("synchronized ");
if ((mod & NATIVE) != 0) sb.append("native ");
if ((mod & STRICT) != 0) sb.append("strictfp ");
if ((mod & INTERFACE) != 0) sb.append("interface ");
if ((len = sb.length()) > 0) /* trim trailing space */
return sb.toString().substring(0, len-1);
return "";
}
通过源码,我们应当很容易的发现,在Modifier类中的toString(int mod)方法中,我们进行了转换的操作。
public class GetConstructorDemo03{
public static void main(String args[]){
Class<?> c1 = null ; // 声明Class对象
try{
c1 = Class.forName("com.chen.yuan.vo.Person") ; // 实例化对象
}catch(ClassNotFoundException e){
e.printStackTrace() ;
}
Constructor<?> con[] = c1.getConstructors() ; // 取得一个类中的全部构造
for(int i=0;i<con.length;i++){
Class<?> p[] = con[i].getParameterTypes() ; // 得到构造方法中的全部参数
System.out.print("构造方法:" ) ; // 输出构造,直接打印
int mo = con[i].getModifiers() ; // 得到所要的访问权限
System.out.print(Modifier.toString(mo) + " ") ; // 得到修饰符
System.out.print(con[i].getName()) ; // 取得构造方法的名字
System.out.print("(") ;
for(int j=0;j<p.length;j++){
System.out.print(p[j].getName() + " arg" + i) ;
if(j<p.length-1){
// 判断此是否是最后一个参数
System.out.print(","); // 输出“,”
}
}
System.out.println("){}") ;
}
}
};
输出:
构造方法:public com.chen.yuan.vo.Person(java.lang.String arg0,int arg0){}
构造方法:public com.chen.yuan.vo.Person(java.lang.String arg1){}
构造方法:public com.chen.yuan.vo.Person(){}
四、 取得全部方法
要想取得一个类中的全部方法,可以通过Class类中的getDeclaredMethods()方法,此方法返回一个Method类的对象数组,然后我们可以通过Method类,去进一步得到方法的详细信息。
public class GetMethodDemo{
public static void main(String args[]){
Class<?> c1 = null ; // 声明Class对象
try{
c1 = Class.forName("com.chen.yuan.vo.Person") ; // 实例化对象
}catch(ClassNotFoundException e){
e.printStackTrace() ;
}
Method m[] = c1.getMethods() ; // 取得全部方法
for(int i=0;i<m.length;i++){
Class<?> r = m[i].getReturnType() ; // 得到返回值类型
Class<?> p[] = m[i].getParameterTypes() ; // 取得全部参数的类型
int xx = m[i].getModifiers() ; // 得到修饰符
System.out.print(Modifier.toString(xx) + " ") ; // 输出修饰符
System.out.print(r + " ") ;
System.out.print(m[i].getName()) ;
System.out.print("(") ;
for(int j=0;j<p.length;j++){
System.out.print(p[j].getName() + " " + "arg" + j) ;
if(j<p.length-1){
System.out.print(",") ;
}
}
Class<?> ex[] = m[i].getExceptionTypes() ; // 取出异常
if(ex.length>0){
System.out.print(") throws ") ;
}else{
System.out.print(")") ;
}
for(int j=0;j<ex.length;j++){
System.out.print(ex[j].getName()) ;
if(j<p.length-1){
System.out.print(",") ;
}
}
System.out.println() ;
}
}
};
输出;
public class java.lang.String getName()
public void setName(java.lang.String arg0)
public void sayChina()
public class java.lang.String sayHello(java.lang.String arg0,int arg1)
public void setAge(int arg0)
public int getAge()
public final void wait(long arg0,int arg1) throws java.lang.InterruptedException,
public final native void wait(long arg0) throws java.lang.InterruptedException
public final void wait() throws java.lang.InterruptedException
public boolean equals(java.lang.Object arg0)
public class java.lang.String toString()
public native int hashCode()
public final native class java.lang.Class getClass()
public final native void notify()
public final native void notifyAll()
五、 取得类中的属性
Class类中提供了两种不同的操作,可以获得Field:
1) 得到实现的接口或父类中的公共属性: public Field[] getFields() throws SecurityException
2) 得到本类中的全部属性: public Field[] getDeclaredFields() throws SecurityException
public class GetFieldDemo{
public static void main(String args[]){
Class<?> c1 = null ; // 声明Class对象
try{
c1 = Class.forName("com.chen.yuan.vo.Person") ; // 实例化对象
}catch(ClassNotFoundException e){
e.printStackTrace() ;
}
{ // 本类属性
Field f[] = c1.getDeclaredFields() ; // 取得本类中的属性
for(int i=0;i<f.length;i++){
Class<?> r = f[i].getType() ; // 得到属性类型
int mo = f[i].getModifiers() ; // 得到修饰符的数字
String priv = Modifier.toString(mo) ; // 还原修饰符
System.out.print("本类属性:") ;
System.out.print(priv + " ") ;
System.out.print(r.getName() + " ") ; // 得到属性类型
System.out.print(f[i].getName()) ; // 输出属性名称
System.out.println(" ;") ;
}
}
{ // 公共属性
Field f[] = c1.getFields() ; // 取得本类中的公共属性
for(int i=0;i<f.length;i++){
Class<?> r = f[i].getType() ; // 得到属性类型
int mo = f[i].getModifiers() ; // 得到修饰符的数字
String priv = Modifier.toString(mo) ; // 还原修饰符
System.out.print("公共属性:") ;
System.out.print(priv + " ") ;
System.out.print(r.getName() + " ") ; // 得到属性类型
System.out.print(f[i].getName()) ; // 输出属性名称
System.out.println(" ;") ;
}
}
}
};
输出:
本类属性:private java.lang.String name ;
本类属性:private int age ;
公共属性:public static final java.lang.String NATIONAL ;
公共属性:public static final java.lang.String AUTHOR ;
Java反射机制(二):通过反射取得类的结构的更多相关文章
- java 面向对象(二十):类的结构:代码块
类的成员之四:代码块(初始化块)(重要性较属性.方法.构造器差一些)1.代码块的作用:用来初始化类.对象的信息2.分类:代码块要是使用修饰符,只能使用static分类:静态代码块 vs 非静态代码块3 ...
- java 中利用反射机制获取和设置实体类的属性值
摘要: 在java编程中,我们经常不知道传入自己方法中的实体类中到底有哪些方法,或者,我们需要根据用户传入的不同的属性来给对象设置不同的属性值,那么,java自带的反射机制可以很方便的达到这种目的,同 ...
- 反射、反射机制、类加载、Class类专题复习
一.反射概念 1.反射机制允许程序在执行期借助于ReflectionAPI取得任何类的内部信息(比如成员变量,构造器,成员方法等等),并能操作对象的属性及方法.反射在设计模式和框架底层都会用到. 2. ...
- 使用反射机制实现jQuery调用ashx类中的指定方法
使用反射机制实现jQuery调用ashx类中的指定方法 近期用asp.net做个小网站,但又不喜欢使用asp.net的服务器端控件,经过一番思量后确定前端采用原始的html.后台采用Linq to ...
- JAVA基础(二)—— 常用的类与方法
JAVA基础(二)-- 常用的类与方法 1 Math类 abs ceil floor 绝对值 大于等于该浮点数的最小整数 小于等于该浮点数的最大整数 max min round 两参数中较大的 两参数 ...
- 利用java反射机制 读取配置文件 实现动态类载入以及动态类型转换
作者:54dabang 在spring的学习过程之中,我们能够看出通过配置文件来动态管理bean对象的优点(松耦合 能够让零散部分组成一个总体,而这些总体并不在意之间彼此的细节,从而达到了真正的物理上 ...
- 浅说Java中的反射机制(二)
写过一篇Java中的反射机制,不算是写,应该是抄了,因为那是别人写的,这一篇也是别人写的,摘抄如下: 引自于Java基础--反射机制的知识点梳理,作者醉眼识朦胧.(()为我手记) 什么是反射? 正常编 ...
- JAVA中反射机制二
声明:如需转载请说明地址来源:http://www.cnblogs.com/pony1223 反射二 利用反射创建对象 1.利用反射创建对象,首先我们创建一个类,类里面,我们知道构造函数有默认的构造函 ...
- java反射机制与动态加载类
什么是java反射机制? 1.当程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言.我们认为java并不是动态语言,但是它却有一个非常突出的动态相关机制,俗称:反射. IT行业里这么说,没有 ...
- Java反射机制二 获取方法的返回值或参数的泛型信息
在使用反射机制时,我们经常需要知道方法的参数和返回值类型,很简单 ,下面上示例,示例中的两个方法非常相似 package deadLockThread; import java.lang.refle ...
随机推荐
- php7不再支持HTTP_RAW_POST_DATA,微信支付$GLOBALS[‘HTTP_RAW_POST_DATA’]获取不到数据,
升级到php7后, 发现旧的web系统有些问题, 查看后才发现原来是php7不再支持HTTP_RAW_POST_DATA 原来系统一些地方, 使用$GLOBALS[‘HTTP_RAW_POST_DAT ...
- excel怎么并排查看两个工作表
excel怎么并排查看两个工作表 excel怎么并排查看两个工作表?excel打开一个窗口想要同时查看两个工作表中的数据,类似于word中的分栏效果,该怎么实现呢?EXCEL是一个使用最多的办公软件, ...
- AndroidStudio离线打包MUI集成JPush极光推送并在java后端管理推送
1.AndroidStudio离线打包MUI 如何离线打包请参看上篇随笔<AndroidStudio离线打包MUI> 2.集成极光推送 官方文档:https://docs.jiguang. ...
- 用蒙特卡罗方法解非线性规划MATLAB
共需要三个M文件,主程序为randlp.m randlp.m: function [sol,r1,r2]=randlp(a,b,n) %随机模拟解非线性规划 debug=1; a=0; %试验点下界 ...
- re模块相关
一.正则表达式中的转义: "\" 表示转义符 [()+*?/$.] 在字符组中一些特殊的字符会现出原形 所有的\w \d \s (\n,\t) \W \D \S 都表示它原本的意义 ...
- 删除重复节点 Remove Duplicates from Sorted List
Given a sorted linked list, delete all duplicates such that each element appear only once. For examp ...
- 【JZOJ3852】【NOIP2014八校联考第2场第2试9.28】单词接龙(words)
DDD Bsny从字典挑出N个单词,并设计了接龙游戏,只要一个单词的最后两个字母和另一个单词的前两个字母相同,那么这两个单词就可以有序的连接起来. Bsny想要知道在所给的所有单词中能否按照上述方式接 ...
- 【JZOJ4923】【NOIP2017提高组模拟12.17】巧克力狂欢
题目描述 Alice和Bob有一棵树(无根.无向),在第i个点上有ai个巧克力.首先,两人个选择一个起点(不同的),获得点上的巧克力:接着两人轮流操作(Alice先),操作的定义是:在树上找一个两人都 ...
- HDU 4193
本题思路:用sum[]数组维护前缀和, 当然这里需要把原数组扩大为原来的两倍. 然后对于任意一个长度为n的区间 k.....k+n-1,如果有该区间内的最小值大于等于sum[k-1]那么该种情况就符合 ...
- 【调试】Visual Studio 调试小技巧(2)-从查看窗口得到更多信息(转载)
在使用Visual Studio开发调试程序时,我们经常需要打开查看窗口(Watch)来分析变量.有时在查看窗口显示的内容不是很直观.为了能从查看窗口的变量中得到更多的信息,我们需要一些小的技巧.下面 ...