浅析java反射机制
java的反射机制是强大且不安全的,他的强大之处在与可以实现动态创建对象和编译,体现出了很大的灵活性,体现了多态的应用,有利于降低类之间的耦合程度,
不安全体现在,可以通过反射修改类内部私密属性,破坏了java封装的特性。
Java中是用Class.forName(classname)来反射类。Class.forName(classname)方法实际上是调用了Class类中的Class.forNameclass(name,true,currentLoader)
参数:
name - 所需类的完全限定名;
initialize - 是否必须初始化类;
loader - 用于加载类的类加载器。
currentLoader则是通过调用ClassLoader.getCallerClassLoader()获取当前类加载器的。
类要想使用,必须用类加载器加载,所以需要加载器。
反射机制,不是每次都去重新反射,而是提供了cache,
每次都会需要类加载器去自己的cache中查找,如果可以查到,则直接返回该类。
类加载器的类加载过程。先检查自己是否已经加载过该类,如果加载过,则直接返回该类,若没有则调用父类的loadClass方法,
如果父类中没有,则执行findClass方法去尝试加载此类,也就是我们通常所理解的片面的"反射"了。
这个过程主要通过ClassLoader.defineClass方法来完成。
defineClass 方法将一个字节数组转换为 Class 类的实例(任何类的对象都是Class类的对象)。
这种新定义的类的实例需要使用 Class.newInstance 来创建,而不能使用new来实例化。
在Java中,每个class都有一个相应的Class对象。也就是说,当我们编写一个类(.java文件),编译完成后,
在生成的.class文件中,就会产生一个Class对象,用于表示这个类的类型信息。
其实说的简单通俗一点,
就是在运行期间,如果我们要产生某个类的对象,
Java虚拟机(JVM)会检查该类型的Class对象是否已被加载。
如果没有被加载,JVM会根据类的名称找到.class文件并加载它。
一旦某个类型的Class对象已被加载到内存,就可以用它来产生该类型的所有对象。
在java中有三种类类加载器。
1)Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。
2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类
3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。
类的装载是通过类加载器完成的,加载器将.class文件的二进制文件装入JVM的方法区,并且在堆区创建描述这个类的java.lang.Class对象。用来封装数据。 但是同一个类只会被类装载器装载以前
链接就是把二进制数据组装为可以运行的状态。
链接分为校验,准备,解析这3个阶段:
校验一般用来确认此二进制文件是否适合当前的JVM(版本),
准备就是为静态成员分配内存空间,。并设置默认值
解析指的是转换常量池中的代码作为直接引用的过程,直到所有的符号引用都可以被运行程序使用(建立完整的对应关系)。
完成之后,类型也就完成了初始化,初始化之后类的对象就可以正常使用了,直到一个对象不再使用之后,将被垃圾回收。释放空间。当没有任何引用指向Class对象时就会被卸载,结束类的生命周期。
反射方法:
获得方式
1、getClass()
2、Class.getSuperclass()
3、运用static method------Class.forName()(最常被使用)
4、运用primitive wrapper classes的TYPE 语法
创建对象
Objecto = c.newInstance();(无参构造方法)
获取属性
Field[] fs = c.getDeclaredFields();
获取特定属性
//获取类
Class c = Class.forName("User");
//获取id属性
Field idF = c.getDeclaredField("id");
//实例化这个类赋给o
Object o = c.newInstance();
//打破封装
idF.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。
//给o对象的id属性赋值"110"
idF.set(o, "110"); //set
//get
System.out.println(idF.get(o));
取方法,和构造方法,不再详细描述
getDeclaredMethods()
获取所有的方法
getReturnType()
获得方法的放回类型
getParameterTypes()
获得方法的传入参数类型
getDeclaredMethod("方法名",参数类型.class,……)
获得特定的方法
构造方法关键字
含义
getDeclaredConstructors()
获取所有的构造方法
getDeclaredConstructor(参数类型.class,……)
获取特定的构造方法
父类和父接口
含义
getSuperclass()
获取某类的父类
getInterfaces()
获取某类实现的接口

浙公网安备 33010602011771号