博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java反射机制
阅读量:5290 次
发布时间:2019-06-14

本文共 9017 字,大约阅读时间需要 30 分钟。

说到反射,相信有过编程经验的人都不会陌生。反射机制让Java变得更加的灵活。反射机制在Java的众多特性中是非常重要的一个。下面就让我们一点一点了解它是怎么一回事。

什么是反射

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

反射有什么用

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

2,在运行时构造任意一个类的对象;

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

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

5,生成动态代理。

反射的API

学习一门语言,一种比较好的方式就是看它的API文档,因为它的API是最权威的,最准确的。下面我们一起看看JDK的API对于反射是如何描述的吧!

与反射有关的所有接口以及类都在java.lang.reflect包里。

接口

接口摘要

表示目前正在此 VM 中运行的程序的一个已注释元素。

GenericArrayType 表示一种数组类型,其组件类型为参数化类型或类型变量。

声明类型变量的所有实体的公共接口。

InvocationHandler 是代理实例的调用处理程序 实现的接口。

成员是一种接口,反映有关单个成员(字段或方法)或构造方法的标识信息。

ParameterizedType 表示参数化类型,如 Collection<String>。

Type 是 Java 编程语言中所有类型的公共高级接口。

TypeVariable 是各种类型变量的公共高级接口。

WildcardType 表示一个通配符类型表达式,如 ?、? extends Number 或 ? super Integer。

类摘要

AccessibleObject 类是 Field、Method 和 Constructor 对象的基类。

Array 类提供了动态创建和访问 Java 数组的方法。

Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。

Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。

Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。

Modifier 类提供了 static 方法和常量,对类和成员访问修饰符进行解码。

Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。

反射操作的 Permission 类。


下面给大家写了一个小实例:

[java] 
  1. package reflection;  
  2.   
  3. public class UserInfo {  
  4.       
  5.     private Integer id;  
  6.     private String userName;  
  7.     private String password;  
  8.     public Integer getId() {  
  9.         return id;  
  10.     }  
  11.     public void setId(Integer id) {  
  12.         this.id = id;  
  13.     }  
  14.     public String getUserName() {  
  15.         return userName;  
  16.     }  
  17.     public void setUserName(String userName) {  
  18.         this.userName = userName;  
  19.     }  
  20.     public String getPassword() {  
  21.         return password;  
  22.     }  
  23.     public void setPassword(String password) {  
  24.         this.password = password;  
  25.     }  
  26.       
  27.     @Override  
  28.     public String toString(){  
  29.         return this.getClass().getName();  
  30.     }  
  31.       
  32. }  


[java] 
  1. package reflection;  
  2.   
  3. public class GetClass {  
  4.   
  5.     public boolean ClassCheck(){  
  6.         try {  
  7.               
  8.             System.out.println("第一种,通过类本身获得对象");  
  9.             Class UserClass = this.getClass();  
  10.             System.out.println("第一种方式成功!类名:"+UserClass.toString()+"\n");  
  11.               
  12.             System.out.println("第二种,通过子类实例获取父类");  
  13.             UserInfo ui = new UserInfo();  
  14.             UserClass = ui.getClass();  
  15.             Class SubUserClass = UserClass.getSuperclass();  
  16.             System.out.println("第二种方式成功!类名:"+SubUserClass.toString()+"\n");  
  17.               
  18.             System.out.println("第三种,通过类名加.class获得对象");  
  19.             Class ForClass = reflection.UserInfo.class;  
  20.             System.out.println("第三种方式成功!类名:"+ForClass.toString()+"\n");  
  21.               
  22.             System.out.println("第四种,通过类名的字符串获得对象");  
  23.             Class ForName = Class.forName("reflection.UserInfo");  
  24.             System.out.println("第四种方式成功!类名:"+ForName.toString()+"\n");  
  25.               
  26.         } catch (Exception e) {  
  27.             e.printStackTrace();  
  28.             return false;  
  29.         }  
  30.         return true;  
  31.     }  
  32.       
  33.     @Override  
  34.     public String toString(){  
  35.         return this.getClass().getName();  
  36.     }  
  37.       
  38.     public static void main(String[] args) {  
  39.         GetClass gc = new GetClass();  
  40.         gc.ClassCheck();  
  41.         if (gc.ClassCheck()) {  
  42.             System.out.println("所有反射全部成功!");  
  43.         }  
  44.         else {  
  45.             System.out.println("反射有问题,请检查!");  
  46.         }  
  47.     }  
  48.   
  49. }  

上面四种方法里面,我用的最多的是第四种,这种一般都是配合配置文件一起用的。反射与配置文件的结合让我们的代码变得非常的灵活,易扩展、以维护。可谓是好处多多呀,所以才有那句”反射反射,程序员的快乐!“一起尽情的快乐吧!

实例一:获得完整的类名

[java] 
  1. package reflection.getclassname;  
  2.   
  3. //获得完整的类名  
  4. public class GetClassName {  
  5.   
  6.     public String getNameByClass() {  
  7.           
  8.         String name = "";  
  9.         System.out.println("通过类本身获得对象");  
  10.         Class UserClass = this.getClass();  
  11.         System.out.println("获得对象成功!\n");  
  12.           
  13.         System.out.println("通过类对象获得类名");  
  14.         name = UserClass.getName();  
  15.         System.out.println("获得类名成功!");  
  16.         return name;  
  17.     }  
  18.     public static void main(String[] args) {  
  19.           
  20.         GetClassName gcn = new GetClassName();  
  21.         System.out.println("类名为:"+gcn.getNameByClass());  
  22.     }  
  23.   
  24. }  
运行结果:

通过类本身获得对象

获得对象成功!
通过类对象获得类名
获得类名成功!
类名为:reflection.getclassname.GetClass Name       

实例二:获得类的属性

[java] 
  1. package reflection.getfields;  
  2.   
  3. import java.lang.reflect.Field;  
  4.   
  5. //获得类的属性  
  6. public class GetFields {  
  7.   
  8.     public static void getFieldNames(String className) {  
  9.           
  10.         try {  
  11.             //获得类名  
  12.             Class c = Class.forName(className);  
  13.             //获得所有属性  
  14.             Field[] fds = c.getFields();  
  15.               
  16.             for (int i=0; i<fds.length; i++)  
  17.             {  
  18.                 String fn = fds[i].getName();  
  19.                 Class tc = fds[i].getType();  
  20.                 String ft = tc.getName();  
  21.                 System.out.println("该属性的名字为:"+fn+",该属性的类型为:"+ft);  
  22.             }  
  23.         }catch (Exception e) {  
  24.             e.printStackTrace();  
  25.         }  
  26.     }  
  27.       
  28.     public static void main(String[] args) {  
  29.         GetFields.getFieldNames("reflection.getfields.FieldInfo");  
  30.     }  
  31.   
  32. }  

运行结果:

该属性的名字为:id,该属性的类型为:java.lang.String

该属性的名字为:username,该属性的类型为:java.lang.String    

实例三:获得类实现的接口

[java] 
  1. package reflection.getinterfaces;  
  2.   
  3. //获得类实现的接口  
  4. public class GetInterfaces {  
  5.   
  6.     public static void getInterfaces(String className) {  
  7.         try {  
  8.             //取得类  
  9.             Class cl = Class.forName(className);  
  10.             Class[] ifs = cl.getInterfaces();  
  11.             for (int i = 0; i<ifs.length;i++)  
  12.             {  
  13.                 String IName = ifs[i].getName();  
  14.                 System.out.println("该类实现的接口名字为:"+IName);  
  15.             }  
  16.         }catch (Exception e) {  
  17.             e.printStackTrace();  
  18.         }  
  19.     }  
  20.       
  21.     public static void main(String[] args) {  
  22.         GetInterfaces.getInterfaces("reflection.getinterfaces.Student");  
  23.     }  
  24.   
  25. }  
运行结果:

该类实现的接口名字为:reflection.getinterfaces.Person    

实例四:获得类及其属性的修饰符

[java] 
  1. package reflection.getmodifiers;  
  2.   
  3. import java.lang.reflect.Field;  
  4. import java.lang.reflect.Modifier;  
  5.   
  6. import reflection.UserInfo;  
  7.   
  8. //获得类及其属性的修饰符  
  9. public class GetModifiers {  
  10.   
  11.     private String username = "liu shui jing";  
  12.     float f = Float.parseFloat("1.000");  
  13.     public static final int i = 37;  
  14.       
  15.     //获得类的修饰符  
  16.     public static String useModifiers(UserInfo ui) {  
  17.           
  18.         Class uiClass = ui.getClass();  
  19.         int m = uiClass.getModifiers();  
  20.         return Modifier.toString(m);  
  21.           
  22.     }  
  23.       
  24.     //获得本类属性的修饰符  
  25.     public void checkThisClassModifiers() {  
  26.           
  27.         Class tc = this.getClass();       
  28.         Field fl[] = tc.getDeclaredFields();  
  29.       
  30.         for(int i=0;i<fl.length;i++)  
  31.         {  
  32.             System.out.println("第"+(i+1)+"个属性的修饰符为:"+Modifier.toString(fl[i].getModifiers()));  
  33.         }  
  34.           
  35.     }  
  36.     public static void main(String[] args) {  
  37.           
  38.         //获得类的修饰符  
  39.         UserInfo ui =new UserInfo();  
  40.         System.out.println("获得这个类的修饰符:"+GetModifiers.useModifiers(ui)+"\n");  
  41.           
  42.         //获得本类属性的修饰符  
  43.         GetModifiers gm = new GetModifiers();  
  44.         gm.checkThisClassModifiers();  
  45.           
  46.     }  
  47.   
  48. }  
运行结果:

获得这个类的修饰符:public

 

第1个属性的修饰符为:private

第2个属性的修饰符为:

第3个属性的修饰符为:public static final      

实例五:获得类的构造函数

[java] 
  1. package reflection.getconstructor;  
  2.   
  3. import java.lang.reflect.Constructor;  
  4.   
  5. //获得类的构造函数  
  6. public class GetConstructor {  
  7.   
  8.     //构造函数一  
  9.     GetConstructor(int a) {  
  10.           
  11.     }  
  12.       
  13.     //构造函数二  
  14.     GetConstructor(int a, String b) {  
  15.           
  16.     }  
  17.       
  18.     public static void getConstructorInfo(String className) {  
  19.         try {  
  20.             //获得类的对象  
  21.             Class cl =Class.forName(className);  
  22.             System.out.println("获得类"+className+"所有的构造函数");  
  23.             Constructor ctorlist[] = cl.getDeclaredConstructors();  
  24.             System.out.println("遍历构造函数\n");  
  25.             for(int i =0 ; i<ctorlist.length; i++)  
  26.             {  
  27.                 Constructor con = ctorlist[i];  
  28.                 System.out.println("这个构造函数的名字为:"+con.getName());  
  29.                 System.out.println("通过构造函数获得这个类的名字为:"+con.getDeclaringClass());  
  30.                   
  31.                 Class cp[] = con.getParameterTypes();  
  32.                 for (int j=0; j<cp.length; j++)  
  33.                 {  
  34.                     System.out.println("参数 "+j+" 为 "+cp[j]+"\n");  
  35.                 }  
  36.             }  
  37.         }catch (Exception e) {  
  38.                 System.err.println(e);            
  39.         }  
  40.     }  
  41.     public static void main(String[] args) {  
  42.         GetConstructor.getConstructorInfo("reflection.getconstructor.GetConstructor");  
  43.     }  
  44.   
  45. }  
运行结果:

获得类reflection.getconstructor.GetConstructor所有的构造函数

遍历构造函数

 

这个构造函数的名字为:reflection.getconstructor.GetConstructor

通过构造函数获得这个类的名字为:class reflection.getconstructor.GetConstructor       

参数 0 为 int

 

这个构造函数的名字为:reflection.getconstructor.GetConstructor

通过构造函数获得这个类的名字为:class reflection.getconstructor.GetConstructor

参数 0 为 int

 

参数 1 为 class java.lang.String

实例六:获得父类

[java] 
  1. package reflection.getparentclass;  
  2.   
  3. //获得父类  
  4. public class GetParentClass {  
  5.   
  6.     public static String getParentClass(UserInfoMore uim) {  
  7.           
  8.         //获得父类  
  9.         Class uimc = uim.getClass().getSuperclass();  
  10.         System.out.println("获得父类的名字为:"+uimc.getName());  
  11.         return uimc.getName();  
  12.           
  13.     }  
  14.       
  15.     public static void searchParentClass() {  
  16.           
  17.     }  
  18.       
  19.     public static void main(String[] args) {  
  20.           
  21.         UserInfoMore uim = new UserInfoMore();  
  22.         System.out.println("成功获得UserInfoMore的父类:"+GetParentClass.getParentClass(uim));  
  23.           
  24.     }  
  25.   
  26. }  
运行结果:

获得父类的名字为:reflection.UserInfo

成功获得UserInfoMore的父类:reflection.UserInfo   

实例七:获得类的方法

[java] 
  1. package reflection.getmethod;  
  2.   
  3. import java.lang.reflect.Method;  
  4.   
  5. //获得类的方法  
  6. public class GetMethod {  
  7.   
  8.     public static void getMethods(String className) {  
  9.         try {  
  10.             System.out.println("开始遍历类"+className+".class");  
  11.             //获得类名  
  12.             Class cls = Class.forName(className);  
  13.             //利用方法获得所有该类的方法  
  14.             System.out.println("利用类的getDeclaredMethods获得类的所有方法");  
  15.             Method ml[] =cls.getDeclaredMethods();  
  16.             System.out.println("遍历获得的方法数组\n");  
  17.             for (int i = 0 ;i<ml.length;i++)  
  18.             {  
  19.                 System.out.println("开始遍历第"+(i+1)+"个方法");  
  20.                 Method m = ml[i];  
  21.                 System.out.println("开始获取方法的变量类型");  
  22.                 Class ptype[] = m.getParameterTypes();  
  23.                 for (int j=0; j<ptype.length; j++)  
  24.                 {  
  25.                     System.out.println("方法参数"+j+"类型为"+ptype[j]);  
  26.                 }  
  27.                 Class gEx[] = m.getExceptionTypes();  
  28.                 for (int j=0 ; j<gEx.length; j++)  
  29.                 {  
  30.                     System.out.println("异常"+j+"为"+ gEx[j]);  
  31.                 }  
  32.                   
  33.                 System.out.println("该方法的返回值类型为:"+m.getReturnType()+"\n");  
  34.                   
  35.             }  
  36.         }catch (Exception e) {  
  37.             e.printStackTrace();  
  38.         }  
  39.     }  
  40.       
  41.     public static void main(String[] args) {  
  42.         GetMethod.getMethods("reflection.UserInfo");  
  43.     }  
  44.   
  45. }  
运行结果:

开始遍历类reflection.UserInfo.class

利用类的getDeclaredMethods获得类的所有方法         

遍历获得的方法数组

 

开始遍历第1个方法

开始获取方法的变量类型

该方法的返回值类型为:class java.lang.String

 

开始遍历第2个方法

开始获取方法的变量类型

该方法的返回值类型为:class java.lang.Integer

 

开始遍历第3个方法

开始获取方法的变量类型

方法参数0类型为class java.lang.String

该方法的返回值类型为:void

 

开始遍历第4个方法

开始获取方法的变量类型

该方法的返回值类型为:class java.lang.String

 

开始遍历第5个方法

开始获取方法的变量类型

方法参数0类型为class java.lang.Integer

该方法的返回值类型为:void

 

开始遍历第6个方法

开始获取方法的变量类型

该方法的返回值类型为:class java.lang.String

 

开始遍历第7个方法

开始获取方法的变量类型

方法参数0类型为class java.lang.String

该方法的返回值类型为:void

 

这次实例不少吧,而且这些小例子都比较简单,相信大家都可以轻松秒懂。上面一些例子的代码并不是完整的,有些只有一些关键代码,如果想要完整的代码请戳下面的链接。最后祝大家学习愉快!

转自

转载于:https://www.cnblogs.com/wujiazhong/p/9526980.html

你可能感兴趣的文章
javascript学习教程之---如何从一个tab切换到banner幻灯片的转换
查看>>
psp进度统计
查看>>
perl字符串映射函数
查看>>
鱼和豆腐一起吃
查看>>
转载:编剧技巧思路乱谈
查看>>
Linux centos7 rsync工具介绍、rsync常用选项、rsync通过ssh同步
查看>>
函数堆栈
查看>>
关于在linux系统下安装jdk
查看>>
请帮我看看这个页面,红色部份如何改才能保存到ACCess数据库中
查看>>
Oracle数据库初学者入门教程
查看>>
PHP实现栈(Stack)数据结构
查看>>
python常见问题及解决
查看>>
[原创]Java 的传值小例子
查看>>
【MySQL学习】安装和配置 服务无法启动 没有报告任何错误
查看>>
C# 修饰符
查看>>
JavaScript启示录
查看>>
我需要什么样的浏览器?
查看>>
取textaera里的值
查看>>
java设计模式1--工厂方法模式(Factory Method)
查看>>
博客第一弹—聊聊HTML的那些事
查看>>