java梳理-反射
2.JAVA反射机制API及功能
获取类的Class对象
获取类的Fields
获取类的Method
获取类的Constructor
新建类的实例
Class<T>的函数newInstance
通过Constructor对象的方法newInstance
3调用类的函数
调用private函数
4设置/获取类的属性值
private属性
Java反射是Java被视为动态(或准动态)语言的一个关键性质。
这个机制同意程序在执行时透过Reflection APIs取得不论什么一个已知名称的class的内部信息,包含其modifiers(诸如public, static 等)、superclass(比如Object)、实现之interfaces(比如Cloneable)。也包含fields和methods的全部信息,并可于执行时改变fields内容或唤起methods。
Java反射机制容许程序在执行时载入、探知、使用编译期间全然未知的classes。换言之,Java能够载入一个执行时才得知名称的class,获得其完整结构。
这样的“看透”class的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。
Class类:代表一个类,位于java.lang包下。
Field类:代表类的成员变量(成员变量也称为类的属性)。
Method类:代表类的方法。
Constructor类:代表类的构造方法。
Array类:提供了动态创建数组,以及訪问数组的元素的静态方法。
获取类的Class对象:
要想使用反射,首先须要获得待操作的类所相应的Class对象。
Java中,不管生成某个类的多少个对象。这些对象都会相应于同一个Class对象。
这个Class对象是由JVM生成的,通过它可以获悉整个类的结构。
经常使用的获取Class对象的3种方式:
1).使用Class类的静态方法。比如: Class.forName("java.lang.String");
2).使用类的.class语法。如: String.class;
3).使用对象的getClass()方法。如:String str = "aa";
Class<? > classType1 = str.getClass();
获取类的Fields 能够通过反射机制得到某个类的某个属性,然后改变相应于这个类的某个实例的该属性值。JAVA 的Class<T>类提供了几个方法获取类的属性。
| public FieldgetField(String name) | 返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段 |
| public Field[] getFields() |
返回一个包括某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的全部可訪问公共字段 |
| public FieldgetDeclaredField(Stringname) | 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段 |
| public Field[] getDeclaredFields() |
返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的全部字段 |
public static void main(String[] args) throws ClassNotFoundException {
// TODO Auto-generated method stub Class<?> pc3 = Class.forName("reflect.Person");
Field[] fields=pc3.getFields();
for (Field f : fields)
{
System.out.println("field:"+f);
}
Field[] fields2= pc3.getDeclaredFields();
for (Field f : fields2)
{
System.out.println("d field:"+f);
}
}执行结果:
field:public java.lang.String reflect.Person.name
d field:private java.lang.String reflect.Person.password
d field:public java.lang.String reflect.Person.name
可见getFields和getDeclaredFields差别:getFields返回的是申明为public的属性,包含父类中定义。
getDeclaredFields返回的是指定类定义的全部定义的属性,不包含父类的。
获取类的Method
通过反射机制得到某个类的某个方法,然后调用相应于这个类的某个实例的该方法
Class<T>类提供了几个方法获取类的方法。
| public MethodgetMethod(String name,Class<?>... parameterTypes) |
返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法 |
| public Method[] getMethods() |
返回一个包括某些 Method 对象的数组。这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member |
|
public MethodgetDeclaredMethod(Stringname,Class<?>... |
返回一个 Method 对象。该对象反映此 Class 对象所表示的类或接口的指定已声明方法 |
| public Method[] getDeclaredMethods() |
返回 Method 对象的一个数组。这些对象反映此 Class 对象表示的类或接口声明的全部方法,包含公共、保护、默认(包)訪问和私有方法,但不包含继承的方法 |

依据输出。注意getMethods与getDeclaredMethods的差别。
获取类的Constructor
通过反射机制得到某个类的构造器,然后调用该构造器创建该类的一个实例
Class<T>类提供了几个方法获取类的构造器。
|
public Constructor<T> getConstructor(Class<? >... |
返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法 |
|
public Constructor<?>[] getConstructors() |
返回一个包括某些 Constructor 对象的数组。这些对象反映此 Class 对象所表示的类的全部公共构造方法 |
|
public Constructor<T> |
返回一个 Constructor 对象。该对象反映此 Class 对象所表示的类或接口的指定构造方法 |
|
public Constructor<?>[] |
返回 Constructor 对象的一个数组。这些对象反映此 Class 对象表示的类声明的全部构造方法。它们是公共、保护、默认(包)訪问和私有构造方法 |
Constructor<?>[] cons=pc3.getConstructors();
for (int i = 0; i < cons.length; i++) {
System.out.println("cons: "+cons[i]);
}
输出:

3.调用方法:
通过反射获取类的Field对象,调用Field方法设置或获取值

跟上面类似。訪问私有属性失败。
此外还须要设置訪问权限。
例如以下:
2.1.先检查 AccessibleObject的override属性是否为true。
AccessibleObject是Method,Field,Constructor的父类,override属性默觉得false,可调用setAccessible方法改变,假设设置为true,则表示能够忽略訪问权限的限制,直接调用。
2.2.假设不是ture,则要进行訪问权限检測。用Reflection的quickCheckMemberAccess方法先检查是不是public的,假设不是再用Reflection.getCallerClass(1)方法获得到调用这种方法的Class,然后做是否有权限訪问的校验,校验之后缓存一次。以便下次假设还是这个类来调用就不用去做校验了。直接用上次的结果,(非常奇怪用这样的方式缓存,由于这样的方式假设下次换个类来调用的话,就不用会缓存了,而再验证一遍,把这次的结果做为缓存。但上一次的缓存结果就被冲掉了。这是一个非常easy的缓冲机制,仅仅适用于一个类的反复调用)。
2.3.调用MethodAccessor的invoke方法。每一个Method对象包括一个root对象,root对象里持有一个MethodAccessor对象。我们获得的Method独享相当于一个root对象的镜像,全部这类Method共享root里的MethodAccessor对象,(这个对象由ReflectionFactory方法生成,ReflectionFactory对象在Method类中是static final的由native方法实例化)。
每一个实际的Java方法仅仅有一个相应的Method对象作为root,这个root是不会暴露给用户的,而是每次在通过反射获取Method对象时新创建Method对象把root包装起来再给用户。
在第一次调用一个实际Java方法相应得Method对象的invoke()方法之前,实现调用逻辑的MethodAccessor对象还没创建;等第一次调用时才新创建MethodAccessor并更新给root,然后调用MethodAccessor.invoke()真正完毕反射调用。

推断为空 要先reflectionFactory创建,

为了权衡两个版本号的性能,Sun的JDK使用了“inflation”的技巧:让Java方法在被反射调用时。开头若干次使用native版。等反射调用次数超过阈值时则生成一个专用的MethodAccessor实现类。生成当中的invoke()方法的字节码,以后对该Java方法的反射调用就会使用Java版。
以下相应源代码:

每次NativeMethodAccessorImpl.invoke()方法被调用时,都会添加一个调用次数计数器,看超过阈值没有;一旦超过,则调用MethodAccessorGenerator.generateMethod()来生成Java版的MethodAccessor的实现类,而且改变DelegatingMethodAccessorImpl所引用的MethodAccessor为Java版。兴许经由DelegatingMethodAccessorImpl.invoke()调用到的就是Java版的实现了。注意到关键的invoke0()方法是个native方法。它在HotSpot
VM里是由JVM_InvokeMethod()函数所支持的,扯个额外话:想想大多数java有关的东西,假设你愿意去看源代码分析的话。总会找到jvm这层。当然还有大神继续研究Hotspot的里面的C源代码,我认为主要知识点到这一层就算是比較深入了 。
再看DelegatingMethodAccessorImpl:

这是一个间接层,方便在native与Java版的MethodAccessor之间实现切换。
native结束,再看java版本号:MethodAccessorGenerator。
它的基本工作就是在内存里生成新的专用Java类。并将其载入。
private static synchronized String generateName(boolean isConstructor,
boolean forSerialization)
{
if (isConstructor) {
if (forSerialization) {
int num = ++serializationConstructorSymnum;
return "sun/reflect/GeneratedSerializationConstructorAccessor" + num;
} else {
int num = ++constructorSymnum;
return "sun/reflect/GeneratedConstructorAccessor" + num;
}
} else {
int num = ++methodSymnum;
return "sun/reflect/GeneratedMethodAccessor" + num;
}
}
上面贴出来的方法就是产生名字的。至于大神RednaxelaFX贴出来解释GeneratedMethodAccessor1
这段看不懂。如有大神理解,还请多多留言指正。
****************总结********************
http://www.cnblogs.com/onlywujun/p/3519037.html
java梳理-反射的更多相关文章
- JAVA的反射理解
1----------------------------反射的概念----------------------------------------------- JAVA的反射机制是在运行状态中,对 ...
- java的反射
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制. ...
- iOS运行时编程(Runtime Programming)和Java的反射机制对比
运行时进行编程,类似Java的反射.运行时编程和Java反射的对比如下: 1.相同点 都可以实现的功能:获取类信息.属性设置获取.类的动态加载(NSClassFromString(@“clas ...
- Java 类反射机制分析
Java 类反射机制分析 一.反射的概念及在Java中的类反射 反射主要是指程序可以访问.检测和修改它本身状态或行为的一种能力.在计算机科学领域,反射是一类应用,它们能够自描述和自控制.这类应用通过某 ...
- java的反射机制
一.java的反射机制浅谈 最近研究java研究得很给力,主要以看博文为学习方式.以下是我对java的反射机制所产生的一些感悟,希望各位童鞋看到失误之处不吝指出.受到各位指教之处,如若让小生好好感动, ...
- Java:反射
初识Java反射机制: 从上面的描述可以看出Java的反射机制使得Java语言可以在运行时去认识在编译时并不了解的类/对象的信息,并且能够调用相应的方法或修改属性的值.Java反射机制的核心就是允许在 ...
- Java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别
一.Java的反射机制 每个Java程序执行前都必须经过编译.加载.连接.和初始化这几个阶段,后三个阶段如下图: 其中
- java笔记--反射进阶之总结与详解
一.反射进阶之动态设置类的私有域 "封装"是Java的三大特性之一,为了能更好保证其封装性,我们往往需要将域设置成私有的, 然后通过提供相对应的set和get方法来操作这个域.但是 ...
- java笔记--反射机制之基础总结与详解
一.反射之实例化Class类的5种方式: java的数据类型可以分为两类,即引用类型和原始类型(即基本数据类型). 对于每种类型的对象,java虚拟机会实例化不可变的java.lang.Class对象 ...
随机推荐
- ThinkPHP---TP功能类之上传
[一]概论 (1)上传操作的核心操作:移动临时文件(move_upload_file),在ThinkPHP里封装了上传类Upload.class.php (2)上传类Upload.class.php代 ...
- git学习(2)----入门
一.git.github和gitlab的区别 Git诞生于2005年,大神Linus的作品,Github诞生于2008年,没有Git就没有GitHub,Github已成为全球最大的代(tong)码(x ...
- 通过HTTP的HEADER完成各种骚操作
作为一名专业的切图工程师,我从来不care网页的header,最多关心Status Code是不是200.但是HEADER真的很重要啊,客户端从服务器端获取内容,首先就是通过HEADER进行各种沟通! ...
- 【IDEA】【Git】pull代码始终无法pull到最新的代码或者提示pull no items 【解决方式】
最近pull代码老是提示pull no items,但是本地并不是最新的代码,看了各种博客始终无法解决,最后靠自己的方式解决.下面是解决方法. 方法:1.首先git --> repository ...
- Go:内置函数
一.内置函数 close // 主要用来关闭channel len // 用来求长度,比如string.array.slice.map.channel new // 用来分配内存,主要用来分配值类型, ...
- linux下的进程
一.进程的基础: 1.程序:程序是一些保存在磁盘上的指令的有序集合: 2.进程:进程是程序的一次执行过程: 3.进程与程序的关系:①.程序是静态的,进程是动态的: ②.一个程序可以对应多个进程: ...
- No buffer space available错误解决方案
生产环境,突然爆发问题,网络正常,但是报网络不通错误,重启tomcat立刻好使 开始以为是tomcat的问题,调查了很久,后来加上堆栈日志才发现 简单来说,就是1-4分钟之内,使用了大量的http请求 ...
- JavaScript学习总结(12)——2016 年 7 个顶级 JavaScript 框架
当涉及到Web开发时,JavaScript框架往往是一些开发人员和企业最受欢迎的平台.可能,你有机会尝试过一两个顶级的JavaScript框架,但你仍然有点不确定哪个才是最佳的最值得掌握的,或者哪个值 ...
- Convolutions in TensorFlow
Convolutions in TensorFlow Convolutions without training You might already be familiar with the term ...
- [K/3Cloud]进度条控件编程接口
进度条控件编程接口 1.启动进度查询 this.GetControl<ProgressBar>().Start(2) //每2秒查询一次进度 2.汇报进度 在插件中重载 OnQueryP ...