Java反射(详述版)
一、什么是反射?
我们先来看一个例子:
package venus;
public class Student {public String name;public Student(){System.out.println("无参构造方法");}public void doHomework(){System.out.println(name + "正在做作业~~~");}}
我们平常是如何调用Student
类里的方法的?
package venus;
public class Test {public static void main(String[] args) {Student student = new Student(); student.name = "小白";student.doHomework();}
}//结果:
无参构造方法
小白正在做作业~~~
以上这种方法是普通的方法:其中Student student = new Student()
通过new
关键字来创建对象,并调用无参构造方法;接着的student.name = "小白"
是调用的其中的成员变量;student.doHomework()
是调用普通方法。
一般情况下,我们使用某个类时是知道这个类是什么类,是用来做什么的,所以我们可以直接对这个类进行实例化,之后使用这个类的对象进行操作,就例如上面的
但反射则是一开始我们并不知道要初始化的类对象是什么,就无法通过new
关键字来创建对象了;也就是说反射是在运行时才知道要操作的类是什么,并且可以通过相应的方法可以获得这个类完整的样子!
综上所述,反射就是一种新的操作类中成员变量、构造方法和普通方法的机制,它可以将类中的各个组成部分进行剖析,可以得到每个组成部分,然后对每个组成部分进行操作!
二、Class类
要实现对类中的成员变量、构造方法和普通方法的操作,我们需要借助Java自身提供的
java.lang
包下的Class
类和java.lang.reflect
包下的反射API(接口)。
- Class类是Java反射机制的入口,封装了一个类或接口的运行时信息,通过调用Class类的方法可以获取这些信息。
- Class类的特点 :
- 该类在Java.lang包中;
- 该类被final所修饰,即该类不可以被子类继承;
- 该类实现了Serializable接口;
- 该类的构造方法被private所修饰,即不能通过new关键字创建该类的对象。
2.1获取Class实例化对象
获取Class类实例化对象有以下六种方法:
- 通过
Class.forName("包名.类名")
来获取Class类实例:try {Class clazz = Class.forName("venus.Student");//抛出检查时异常,所以使用try-catchSystem.out.println(clazz.getName()); //venus.Student} catch (Exception e) {e.printStackTrace();}
- 通过
类名.class
来获取Class类实例:Class clazz = Student.class;System.out.println(clazz.getName()); //venus.Student
- 如果已创建了引用类型的对象,则可以通过调用对象中的
getClass()
方法来获取Class类实例:Student student = new Student();//已创建了引用类型的对象Class clazz = student.getClass();System.out.println(clazz.getName());
- 如果是基本数据类型,则可以通过
包装类.TYPE
来获取Class类实例,当然,也可以通过基本数据类型.class
获取Class类实例:Class clazz = Integer.TYPE;System.out.println(clazz.getName()); //intclazz = int.class;System.out.println(clazz.getName()); //int
- 通过
元素类型[].class
来获取数组所对应的Class类实例:clazz = String[].class;System.out.println(clazz.getName()); //[Ljava.lang.String;
- 如何获取某个类父类所对应的Class类实例?通过
类名.class.getSuperclass()
来获取:clazz = Student.class.getSuperclass();System.out.println(clazz.getName()); //java.lang.Object
三、 借助Class类某些可以获取对应类中声明的构造方法实例化对象:
其中
getConstructor([参数类型])
只能获取由public
修饰的构造方法Constructor[] getConstructor()
:获取 无参构造方法:Class clazz = Student.class; //获取Class实例化对象 try {Constructor constructor = clazz.getConstructor(); //获取无参构造方法System.out.println(constructor.getName()); //venus.StudentSystem.out.println(constructor); //public venus.Student() } catch (Exception e) {e.printStackTrace(); }
Constructor getConstructor(Class<?>... parameterTypes)
:获取 对应的有参构造方法:Class clazz = Student.class; try {//获取参数类型为String的有参构造方法Constructor constructor = clazz.getConstructor(String.class); System.out.println(constructor.getName()); //venus.StudentSystem.out.println(constructor); //public venus.Student(java.lang.String) } catch (Exception e) {e.printStackTrace(); }
其中
getDeclaredConstructor([参数类型])
可以获取所有的构造方法,不区分访问权限(即使是私有的也可以):Constructor getDeclaredConstructor()
:获取 无参构造方法Class clazz = Student.class; try {//获取无参构造方法Constructor constructor = clazz.getDeclaredConstructor(); System.out.println(constructor.getName()); //venus.StudentSystem.out.println(constructor); //public venus.Student() } catch (NoSuchMethodException e) {e.printStackTrace(); }
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
:获取 对应的有参构造方法:Class clazz = Student.class; try {//获取参数类型为 int的有参构造方法constructor = clazz.getDeclaredConstructor(int.class);System.out.println( constructor.getName()); //venus.StudentSystem.out.println(constructor); //private venus.Student(int) } catch (NoSuchMethodException e) {e.printStackTrace(); }
3.1 通过Constructor
类某些方法获取某个构造方法的的信息:
Class clazz = Student.class;
try {//获取参数类型为 String 和 int的有参构造方法Constructor constructor = clazz.getConstructor(String.class,int.class);
} catch (Exception e) {e.printStackTrace();
}
获取该构造方法的相关信息:
获取该构造方法的类的Class对象(
Class<T> getDeclaringClass()
):Class result = constructor.getDeclaringClass(); System.out.println(result); //class venus.Student
获取该构造方法的修饰符(
int getModifiers()
):int mod = constructor.getModifiers(); String result = Modifier.toString(mod); System.out.println(result); //public
获取该构造方法的名称(
String getName()
):String result = constructor.getName(); System.out.println(result); //venus.Student
获取该构造方法的形参类型对应的Class对象组成的数组
Class[] clazzs = constructor.getParameterTypes(); for (Class c:clazzs) {System.out.println(c); // {class java.lang.String , int} }
- 注意:
getConstructors()
和getConstructor(Class<?>... parameterTypes)
方法无法获取非public类中默认无参构造方法对应的Constructor对象。getDeclaredConstructor()
和getDeclaredConstructor(Class<?>... parameterTypes)
方法可以获取非public类中默认无参构造方法对应的Constructor对象。
操作构造方法 ---- 创建对象:
void setAccessible(boolean flag)
:如果操作的构造方法是私有的,则需要下面一行代码来忽略访问权限:constructor.setAccessible(true);
T newInstance(Object... initargs)
:使用此Constructor对象表示的构造方法来创建声明该构造方法类的新对象。其中initargs为传入该构造方法中的参数,如果该构造方法没有参数,则可设定为null或一个长度为0的数组:Object object = constructor.newInstance("Tom",18); Student stu = (Student) object; //下转型 stu.doHomework();
四、借助Class类某些可以获取对应类中声明的普通方法实例化对象:
Method[] getMethods()
:获取被public修饰的方法(不仅仅限于本类,还包括继承自父类中的public方法)Class clazz = Student.class; Method[] methods = clazz.getMethods(); for (Method method:methods) {System.out.println(method.getName()); }
结果:
Method[] getMethod(String methodName, Class<?>... paramenterTypes)
:获取与该Class对象表示类或接口中方法名和参数类型相匹配的public方法(含继承的)的Method对象:try {Method method = clazz.getMethod("doHomework");System.out.println(method.getName()); //doHomework } catch (Exception e) {e.printStackTrace(); }
Method[] getDeclaredMethods()
:获取一个该Class对象表示类或接口内声明定义的所有访问权限的方法(不含继承的)对应的Method对象数组:Method [] methods = clazz.getDeclaredMethods();//(任何"访问权限"的方法) for (Method method:methods) {System.out.println(method.getName()); }
Method getDeclaredMethod(String methodName Class<?>... parameterTypes)
:获取与该Class对象表示类或接口中方法名和形参类型相匹配的方法(不含继承的)对应的Method对象。
4.1 操作普通方法 ---- 获取普通方法的信息:
- 先获取某个普通方法:
try {//获取方法名为cooking,参数类型为int和String的方法Method method = clazz.getMethod("cooking", int.class, String[].class); } catch (Exception e) {e.printStackTrace(); }
- 获取该普通方法的相关信息:
String getName()
:获取该普通方法的方法名:String result = method.getName();//获取方法名 System.out.println(result); //cooking
Class<?> getDeclaringClass()
:获取该普通方法的类或接口的Class对象:Class c = method.getDeclaringClass();//获取方法的类的Class对象 System.out.println(c); //class venus.Student
int getModifiers()
:获取该普通方法的修饰符(以整数形式),应该使用Modifier类中的toString()
方法对所返回的整数进行解码:int mod = method.getModifiers(); //获取方法的修饰符 String result = Modifier.toString(mod); System.out.println(result); //public static
Class<?>[] getParameterTypes()
:获取该普通方法的形参类型对应Class对象组成的数组。如果方法没有参数,则数组长度为0:Class [] zzs = method.getParameterTypes();//获取方法的参数类型组成的数组 {Integer.YPTE, String[].class} for (Class cla :zzs) {System.out.println(cla.getName()); }
Class<?> getReturnType()
:获取该普通方法的返回值类型所对应的Class对象:Class clazzs = method.getReturnType();//获取方法的返回值类型★ System.out.println(clazzs.getName());
调用该普通方法:
void setAccessible(boolean flag)
:如果该普通方法是非public的,则需要使用下一行代码来忽略访问权限,true表示忽略:method.setAccessible(true);
Object invoke(Object obj, Object... args)
:调用该普通方法并返回Object类型结果(即返回该普通方法的【返回值】,如果没有,则返回null)。obj表示该方法所在类实例,如果方法是静态的,则obj可以指定为null;args表示传入该方法的参数,如果该方法没有参数,则args数组长度可以为0或null:Object object = method.invoke(new Student(),1,new String []{}); //调用这个方法,并返回该方法的【返回值】,如果该方法没有【返回值】,则返回null System.out.println(object);
相关文章:

s9.16作业,员工信息表
转载https://blog.csdn.net/qq_35883464/article/details/83151464 实现员工信息表文件存储格式如下:id,name,age,phone,job1,Alex,22,13651054608,IT2,Egon,23,13304320533,Tearcher3,nezha,25,1333235322,IT 现在需要…

Dubbo+zookeeper使用方法以及注意事项
Dubbozookeeper使用方法以及注意事项最近在一个项目中想做一个数据库查询的服务,目的是将数据库查询这块从程序中脱离出来,形成一个公共的服务平台,大家都可以调用,经过考虑决定选用Dubbozookeeper这个经典的组合来实现࿰…

淘淘经受了一次考验...
18日去香港给一个潜在客户做了一次演示,顺便帮淘淘买了一罐奶粉,因为听说香港的奶粉质量比较好,是原装进口的。下午6点多回到深圳,没想到,听到一个不太好的消息。淘淘的奶奶推车带淘淘出去的时候,不小心&am…

使用MasterPage遇到的问题
最近重新拿起.NET,发现一切变的那么的陌生了,发展得真是快啊。。。在使用MasterPage时,要从一个页面的Form提交数据到另一个页面的Form,应该如何处理?不使用MasterPage的时候,可以直接使用PostBackUrl"…

Machine Learning——DAY1
监督学习:分类和回归 非监督学习:聚类和非聚类 1.分类和聚类的区别: 分类(Categorization or Classification)就是按照某种标准给对象贴标签(label),再根据标签来区分归类。 聚类是指事先没有“标签”而通过某种成团分析找出事物之…

Java的注解
一、注解的概念: 注解并不是一开始就有的,JDK5之前是没有注解的,JDK5及其以后JDK版本才开始支持Java注解! Java注解(Annotation)也叫做元数据,以注解名在代码中存在,它是一种在源代码…

activemq的学习,第一篇
本地的activemq的地址: http://localhost:8161/admin/ win10的启动avtivemq E:\Program Files\ActiveMQ\apache-activemq-5.15.3\bin\win64 win64里面的activemq.bat 消息队列的学习 学习地址2 这是spring集合activemq的地址:github pom.xml引入的依赖&a…

CS Tip 16: 利用注释
译自: http://soup.co.za/weblog/archive/2006/04/07/CS-Tip-16_3A00_-Commenting-out-controls.aspx 当您在修改皮肤时您可以修改任何HTML标记,但是除了带有runat"Server"的除外,删除掉将会产生错误 如果您不想某个控件显示在页面上您可以注释…

今天没有浪费时间,我努力了
7月12日经过暴雨洗礼过的清晨,我晚起了一会,我伧促的洗了把脸,瞪起朦胧胧的双眼,迈着疲惫步子,重复着这条凌乱的街道,10分钟多一点,我就到了公交站点,像往常一样,挤上了8…

动态规划——洛谷_P1057传球游戏
题目: 题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏。这次,老师带着同学们一起做传球游戏。游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹哨子时开始传球&…

多线程1(进程、[创建]线程与生命周期)
一、进程与线程 什么是进程?我们先说说什么是程序? 程序(Program)是为实现特定目标或解决特定问题而用计算机语言(比如Java、C等)编写的命令序列的集合。 进程(process)就是指一个程…

网络操作系统第四章
1. 磁盘的数据结构包括哪些内容? 答:分区,卷,磁盘分区,主分区,扩展分区,逻辑分区,逻辑驱动器,引导分区。 2. 什么是基本磁盘和动态磁盘? (…

广播风暴系列专题(一)广播风暴:发现-端口
近日防火墙经常地检测到"svchost UDP/连入192.168.1.255/137 192.168.1.66/137 1055656/1065732 UDP_WAIT 过滤 8:48:31 C:\WINDOWS\system32\svchost.exe";"services UDP/连出 192.168.1.21/137 192.168.1.255/137 920736/913476 UDP_WAIT 过滤 11:46:3…

显示一个顶层的提示信息
vb里常作,大概的思路就是显示一个顶层的窗体,提示暂时不要动。c#里更简单了MsgDlg msgnewMsgDlg(); msg.TopMosttrue; msg.Show(); System.Windows.Forms.Application.DoEvents();

ArcGIS Engine开发-TOCControl中实现图层的拖放
TOCControl非常好,不用写一行代码就可以将整个地图的图层信息况显示出来;TOCControl也非常坏,提供的接口非常少,我认为有用的只有三个:HitTest,SetBuddyControl,Update,而且Update方法一执行,整…

多线程2(常用的方法:join、interrupt、currentThread、isAlive、setDaemon...)
常用的方法: 1、join()方法:join()方法:执行该方法的线程进入阻塞状态,直到调用该方法的线程结束后再由阻塞状态转为就绪状态。 示例: package venus;import java.util.Date;public class Test {public static void m…
Oracle总结第二篇【视图、索引、事务、用户权限、批量操作】
前言 在Oracle总结的第一篇中,我们已经总结了一些常用的SQL相关的知识点了…那么本篇主要总结关于Oralce视图、序列、事务的一些内容… 在数据库中,我们可以把各种的SQL语句分为四大类… (1)DML(数据操纵语言ÿ…

物联网应用介绍
•物联网的研究背景(概念 | 本质 | 特征 | 发展现状)物联网是新一代信息技术的高度集成和综合运用,已成为全球新一轮科技革命与产业变革的核心驱动和经济社会绿色、智能、可持续发展的关键基础与重要引擎。国家十三五规划纲要明确提出“积极推…

Oracle使用手册(三)---存储过程与触发器
--存储过程/**//*--1.过程的语法结构--参见:http://newland.cnblogs.com/archive/2006/04/05/367531.html--2.执行存储过程begin 存储过程名;end;--创建好的存储过程可以被任何程序调用*/--3.带参数的存储过程/**//* 参数类型 在PL/SQL过程中,可以有3种类型的…

数据结构之【线性表】(顺序表、链表的基本操作实现)
概念线性表:是N个数据元素的有限序列。 顺序表:用一组地址连续的存储单元依次存储【线性表 】的数据元素。(区别于有序表:表中的数据元素存在非递增或非递减有序) 链表:用一组任意的存储单元来存储【线性表…

基于android的天气预报的设计与实现
目录 应用开发技术及开发平台介绍应用需求分析应用功能设计及其描述应用UI展示①开发技术: 本系统是采用面向对象的软件开发方法,基于Android studio开发平台,以Android作为本系统的开发语言实现音乐播放器预定的需求功能。 ②平台介绍 硬件平…

敏捷开发有感!
http://sd.csdn.net/n/20060913/94713.html1.我们最优先要做的是通过尽早的,持续的交付有价值的软件来使客户满意。有一篇文章分析了对于公司构建高质量产品方面有帮助的软件开发实践,其中一个实践表明尽早的交付具有部分功能的系统和系统质量之间具有很…

ng 表单提交验证
http://www.runoob.com/try/try.php?filenametry_ng_validate 转载于:https://www.cnblogs.com/alvin553819/p/7127226.html

Infragistics NetAdvantage 2006 Volume 2 CLR 2.0曲折安装
上个月看到Infragistics NetAdvantage 2006 Volume 2 CLR 2.0(新特性)新鲜出炉,就一直想安装试用。昨天qq上得知已经有人在使用了,赶紧google一个down下来。经过漫长下载等待,满怀希望安装,哪想到快完成的时候居然报错,…

数据结构之【栈】的基本操作C语言实现
引题: 很多人都把【栈】描述成【弹匣】,但我总感觉有点不恰当,因为弹匣从上端【装弹】之后,子弹总是在匣的上层;而元素【进栈】之后,总在栈的下面。 我觉得还是描述成【从下往上向书箱里一层…

编码小记(未整理-持续更新)
----------------基本概念-------------------------------一.位: 计算机存储信息的最小单位,称之为位(bit),音译比特,二进制的一个“0”或一个“1”叫一位。 二.字节 字节(Byte)是一…

使用locate 的正则查询 查找所有main.c
locate支持正则查询的功能, 只需输入locate -r 正则表达式 即可。 现在我想查找所有main.c怎么做? 打开终端,输入shell: locate -r main.c$ PS:$表示结束字符串结束。转载于:https://www.cnblogs.com/the-one/p…

My Favorites
AJAX "Atlas" Control Toolkit HomePage "Atlas" Client Class Library "Atlas" Server Class Library ASP.NET AJAX Roadmap http://www.ajaxian.com 被成为AJAX第一站 . http://www.ajaxmatters.com/ 不仅有讨论XMLHttpRequest 的文…

数据库事务初探
使用事务级别要慎重: 因为事务级别越高,数量越多、限制性更强的锁就会被运用到数据库记录或者表中。同时,更多的锁被运用到数据库和它们的覆盖面越宽,任意两个事务冲突的可能性就越大。 如果有一个冲突(例如两个事务试图获取同一个…

数据结构之【队列】的基本操作C语言实现
直接上图: 循环队列的声明: 0、循环队列的声明 循环队列的基本操作: 1、InitQueue(&Q)(构造一个空队列) 2、DestroyQueue(&Q)(销毁队列Q) 3、ClearQueue(&Q)(清空队列Q&…