目录
1.反射的背景:
java程序中的对象类型有两种:编译时类型和运行时类型,很多时候对象编译时类型和运行时类型不一致。
例如:某些变量和形参的声名类型是Object,但是程序却需要调用该对象运行时类型的方法,该方法不是Object中的方法,那么如何解决呢。
反射虽然在开发中很少使用,但是在框架中使用很常见
2.反射的使用举例:
2.1私有属性、方法,可以用反射打破
1.某类中方法为私有,其它类中想调用该类的方法,则使用反射的方法调用。
反射可以调用:构造器,属性,方法
Persion类
测试方法
思考:
通过反射。可以调用类中的私有结构,这是否和面向对象的封装性有冲突?
封装性体现是否建议调用,private可以表示为建议不要外部调用,反射是另外的角度,是说明我们能不能调用的问题。反射可以不用,但不能没有。
3.Class理解,获取Class实例
3.1.Class的理解:
针对编写好的.java源文件进行编译(使用javac.exe),会生成一个或者多个.class字节码文件。接着,我们使用Java.exe命令对指定的.class文件进行解释运行。这个解释运行的过程中,需要将.class字节码文件加载(使用类的加载器加载)到内存(存放位置为:方法区)中。
*加载到内存中的.clas字节码文件对应的结构为Class的一个实例。
Class指向不一定只是类,还有可能是一个接口。所有java类型!
Class clazz1=Persion.class;//运行时类
Class clazz2=String.class;//运行时类
Class clazz3=User.class;//运行时类
Class clazz4=Comparable.class;//接口
说明:一般我们使用Persion,User类来造对象,我们的这些类又是另外一个类,即:Class类的对象。Class类的本身也是一个类。运行时类在内存中会缓存起来,在整个执行期间,只会加载一次。
3.2.获取Class实例的方式:
四种方式
4.类的加载过程
过程1:类的装载(loading)
将类的class文件读入内存,并为之创建一个java.lang.Class对象。此过程由类的加载器完成
过程2:链接(linking)
>验证(Verify):确保加载类的信息符合JVM规范,例如:字节码文件开头以cafebaba开头
>准备(prepare):正式为类变量(static)分配内存并设置变量默认初始值阶段,这些内存都将在方法区中分配。(不涉及实例变量,实例变量随着对象创建被加载)
>解析(Resolve): 虚拟机常量引用池符号引用(常量名)替换为直接引用(地址)的过程
过程3:初始化(initialization)
编译期中自动收集类中所有动作赋值动作和静态代码块中的语句合并产生的。
5.类的加载器:(了解)详细了解JVM
作用:负责类的加载,并对应于一个Class实例
分类:两种
>BootstrapClassLoader:引导类加载器、启动类加载器
使用C,C++写的,不能通过java代码获取实例
负责加载java的核心库(类似Boolen,String等)
>继承ClassLoader的类加载器
>ExtensionClassLoader:扩展类加载器
>SystemClassLoader/ApplicationClassLoader:我们自定义的类,默认使用的类加载器
>用户自定义类加载器:例如tomcat
6.使用类加载器可获取流,读取配置文件:
通过反射可读取配置文件,配置文件在src包下
Deom.class.getClassLoader.getRescourceAsStream("")
src下有包也可使用该方式读取配置文件,路径为:com/xxx/xxx/config.xml(正斜杠)
或者为:com\\xxx\\xxx\\config.xml(反斜杠)