二 反射机制
反射的引入
如果添加配置文件re.properties指定信息,创建Cat对象并且调用hi方法 使用现有的技术该如何操作?
: 很明显现有的技术是需要改变源代码,创建对象 在利用对象调用hi方法这是十分麻烦的。
这样的需求在学习框架的时候是特别多,(通过外部文件配置,在不修改源代码的情况下,从而控制程序,符合设计模式当中的OCP原则(开闭原则:在不修改源码的情况下,扩展功能))
1 什么是反射
前提--基础知识:
静态语言与动态语言:
动态语言:
- 在运行的时候代码可以根据某些条件改变自身的结构
- 主要的动态语言:Object-c、C# 、Pthon
静态语言:
- 与动态语言相对的,在运行时结构不可以改变的语言
- 主要语言:java 、c 、c++
虽然说java是静态语言 但是java是可以被称为“准动态语言”的。java是有一定的动态性!
可以利用反射机制使java获得类似动态语言的特性。 也使得java的动态性让编程更具有灵活性!这也是java的市场价值所在!
1.1反射的含义
- 反射(Rflection)是java被视为动态语言的关键所在.
- 反射机制允许程序在执行期间借助Reflection API 取得任何类的内部信息,并且能够直接操作任意对象的内部属性以及方法。
加载完类之后,
==>在堆内存当中的方法区会产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。
==>于是,我们可以通过这个对象看到类的结构。
==>这个对象就像一面镜子,通过这个镜子看到类的结构,所以我们形象的称之为:反射。
1.2反射的作用(为什么要反射)
可以在程序运行期间借助Reflection Api获取任何类的内部结构信息,并且能够操作任意对象修改内部属性和方法。这在传统的方式下是不可以的。
1.3反射的应用(通过反射机制可以获得什么(反射机制所提供的功能))
- 在运行期间可以构造一个类的对象
- 在运行期间可以获得一个类的所具有的成员变量和方法
- 在运行期间可以获取泛型信息
- 在运行期间可以处理注解
- 在运行期间可以判断任意一个对象的所属类
- 在运行期间可以调用任意对一个象的成员变量和方法
- 可以生成动态代理
1.4反射的主要类
- java.lang.Class:代表一个类 ,Class对象表示某个类加载后在堆中的对象。
- java.lang.reflection.Filed: 代表类的属性
- java.lang.reflection.Method :代表类的方法
- java.lang.reflection.Constructors :代表类的构造方法
1.5反射机制的优缺点
优点:可以动态的创建和使用对象(框架的核心),使用灵活
缺点:使用反射基本是解释执行,对执行速度有一定的影响。
(对性能有影响,使用反射基本上是一种解释的操作,我们需要告诉jvm,我们希望做什么并且它能够满足我们的需求,这类操作总是慢于直接执行的操作)
1.6反射机制的性能优化
反射机制调优----关闭访问的检查:setAccessible(true)
- Filed、Method和Constructor对象都有setAccessible()方法。
- setAccessible()方法的作用是启动和禁用访问安全检查的开关
- 默认值是false 表示反射的对象执行访问检查 ;true表示反射的对象在执行时取消访问安全检查,提高了反射的效率。
public class ReflectionPerformanceOptimization {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
testTime1();
testTime2();
testTime3();
}
//传统的通过new来创建对象
public static void testTime1(){
Cat cat1 = new Cat();
cat1.cry();
long start = System.currentTimeMillis();
for(int i=0;i<=900000000;i++){
cat1.hi();
}
long end = System.currentTimeMillis();
System.out.println("传统的创建对象执行时间:"+(end-start));
}
public static void testTime2() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class c1 = Class.forName("com.peng.pojo.Cat");
Object o = c1.newInstance();
Method methodName = c1.getMethod("hi");
Method methodName2 = c1.getMethod("cry");
long start = System.currentTimeMillis();
for(int i=0;i<900000000;i++){
methodName.invoke(o);
}
long end = System.currentTimeMillis();
System.out.println("反射机制的创建对象执行时间:"+(end-start));
}
public static void testTime3() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class c1 = Class.forName("com.peng.pojo.Cat");
Object o = c1.newInstance();
Method methodName2 = c1.getMethod("hi");
methodName2.setAccessible(true);//关闭访问安全检查
long start = System.currentTimeMillis();
for (int i=0;i<900000000;i++){
methodName2.invoke(o);
}
long end = System.currentTimeMillis();
System.out.println("反射机制性能优化后创建对象执行时间:"+(end-start));
}
}
1.7反射的原理图
2 Class类
这个Class就像一个镜子 十分重要!!!!!
2.1class的含义
Class对象实在加载类的时候由jvm就已经创建好了 所以 不需要我们创建只需要获取。
- Class也是类,只不过刚好这个类叫Class,也是继承于Object
- Class类不是new出来的,而是系统创建的,所以我们只需要获取。
- 对于某个类的Class对象,在内存当中只有一份,因为类只加载一次(通过ClassLoad类当中的loadclass加载的 在内存当中中有一份 涉及同步)
- 通过Class类可以完整的得到一个类的完整结构(一个类被加载后,类的整个结构都会被封装在Class对象(ReflectionClass中 ),通过一系列的API
- 每一个类的实例通过反射会记得它是由哪一个Class实例所身处个行的
- Class对象是放在堆
- 类的字节码二进制数据是放在方法区当中
2.2如何获取Class类(核心4种,总共6种)
2.2.1 Class.forName()
编译阶段-----
前提:已知一个类的全类名,且该类在类路径下,可以通过Class类的静态方法forName()获取
会抛出ClassNotFoundException错误
应用场景:多用于配置文件,读取类的全路径、加载类
2.2.2 类名.class
加载阶段---
前提:已知一个具体的类,通过class获取,该方式最为安全可靠 ,程序性能最高的
应用场景:多用于参数的传递 比如说通过反射活得对应的构造器对象
2.2.3 对象.getClass()
运行阶段---
前提:已知某个类的实例,调用该实例的getClasss()方法获取Class对象
应用场景:通过创建好的对象,获取Class对象
2.2.4 通过类加载器
类加载----
ClassLoader cl=对象.getClass().getClassLoader();
Class clazz4=cl.loadClass("类的全类名")
2.2.5 基本数据类型获取Class
Class cls5=基本数据类型.class
2.2.6基本数据类型的包装类的获取Class
Class cls6=包装类.TYPE
package com.peng.ClassLei;
import com.peng.pojo.Dog;
/*1获取Class类的方式
(1)Class.forName()
(2)Class类名.class
(3)对象.getclass()
(4)ClassLoader.loadclass()
(5)基本数据类型.class
(6)基本数据类型.TYPE
* */
public class Class02 {
public static void main(String[] args) throws ClassNotFoundException {
String classFullPath="com.peng.pojo.Dog";
//方式一: 源码阶段 利用Class.forName()
Class<?> c1 = Class.forName(classFullPath);
System.out.println(c1);
//方式二: 加载阶段 利用Class本类名.class
Class<Dog> c2 = Dog.class;
System.out.println(c2);
//方式三:运行阶段 利用Dog类的实例对象.getClass()
Dog dog=new Dog();
Class c3 = dog.getClass();
System.out.println(c3);
//方式四: 类加载器 利用ClassLoader.loadclass()
Class<?> c4 = dog.getClass().getClassLoader().loadClass(classFullPath);
System.out.println(c4);
//方式五:基本数据类型的 基本数据类型.class
Class<Integer> c5 = int.class;
System.out.println(c5);
//方式六: 包装类的 基本数据类型.TYPE
Class<Integer> c6 = Integer.TYPE;
System.out.println(c6);
System.out.println(c5.hashCode());
System.out.println(c6.hashCode());
//基本数据类型和其包装类 在反射当中会自动包装和拆箱
///
//
//
}
}
2.3哪些类型可以获取Class类
- class:外部类 成员(成员内部类 静态内部类) 局部内部类 匿名内部类
- interface:接口
- [ ]:数组
- enum:枚举
- annotation :注解
- primitive type: 基本数据类型
- void
package com.peng.ClassLei;
import java.lang.annotation.ElementType;
//所有类型获取Class类(有哪些类型可以获取Class类)
public class Class03 {
public static void main(String[] args) {
Class c1= Object.class;//1所有类
Class c2 = Comparable.class;//2接口
Class c3 = Override.class;//3注解
Class c4 = String[].class;//4数组 4.1一维数组
Class c5 = String[][].class;// 4.2二维数组
Class c6 = ElementType.class;//5枚举
Class c7 = Integer.class; //6基本数据类型
Class c8 = Class.class;//7Class本身
Class c9 = void.class;//8void
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
System.out.println(c4);
System.out.println(c5);
System.out.println(c6);
System.out.println(c7);
System.out.println(c8);
System.out.println(c9);
int[] a = new int[10];
int[] b = new int[100];
System.out.println(a.hashCode());//460141958
System.out.println(b.hashCode());//1163157884
/*1 a和b获取Class的hashCode一样说明其类是同一个,
2 a和b是其的实例化对象这也说明名了为什么a.hashCode和b.hashCode不一样
3 只要元素类型和维度一致就是同一个Class
* */
System.out.println(a.getClass().hashCode());//1956725890
System.out.println(b.getClass().hashCode());//1956725890
}
}
- 1 a和b获取Class的hashCode一样说明其类是同一个,
- 2 a和b是其的实例化对象这也说明名了为什么a.hashCode和b.hashCode不一样
- 3 只要元素类型和维度一致就是同一个Class
2.4Class类的常用方法
3 类加载
3.1基础知识点:
静态加载与动态加载的区别
静态加载:编译时加载相关的类,如果编译则报错,依赖性很强
动态加载:运行时加载相关的类,如果编译时不用该类就不会报错,即使不存在该类也不会报错 降低依赖性。
静态加载
静态加载编译
编译失败:
因为没有编写Dog类
静态加载就是在new 一个对象的时候 比如说 new Dog 但是Dog这个类没有编写 那么编译 javac ClassLoad.java 就会报错
动态加载
动态加载就是说 反射是动态加载 person类没有编写 在编译的时候是可以通过的 但是编译成功后运行java ClassLoad 的时候就是报错因为没有编写Person这个类 如果编写了这个类就会运行成功。
3.2类加载的过程
1 上图中的初始化时是与静态成员有关的 是类加载 而不是new 一个对象(创建一个对象)
2 类加载后内存当中堆区会有类的字节码二进制所对应的类的Class对象 (这是一个数据结构是一个接口)
注意事项:
- 加载和链接阶段时在jvm虚拟机当中实现的不能人为干预。
- 初始化阶段是程序员可以干涉的。
- !!!类加载涉及到的都是一些静态成员!!!!!
3.2.1类加载-加载阶段
加载阶段是
==》将class字节码文件存到内存方法区当中
==》生成一个字节码二进制数据(将原本class字节码文件的静态数据转换为运行时的数据结构),
==》并且同时创建一个代表这个类的Class对象(堆区)。
3.2.2类加载-链接阶段
(1)验证子阶段
- 目的 为了确保Class文件的字节流中包含的信息是否符合当前虚拟机的要求,并且不会危害虚拟机自身的安全
- 包括:文件格式验证(是否一魔教oxcafe babe开头)、元数据验证、字节码验证和符号引用验证
- 可以使用-Xverify:none参数 来关闭大部分的类验证措施,缩短虚拟机类加载的时间
(2)准备子阶段
虚拟机会在准备阶段给静态变量,分配内存并设置默认值(内存是在方法区当中分配的)
(3)解析子阶段
虚拟机将常量池当中符号引用(常量名)转变为直接引用(地址)的过程
2.1.3类加载-初始化阶段
- 到初始化阶段,才是真正的开始执行类中定义的java代码,这个阶段是执行clinit()放大的过程
- 类构造器clinit()方法是由编译器按顺序在源文件出现的次序,一次自动收集类中的所有静态变量的赋值动作和静态代码块的语句,并且进行合并(类构造器是构造类的信息不是,不是构造该类的对象的构造器)
- 虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确的加锁、同步,如果多个线程同事去初始化一个类,那么只会有一个线程去执行这个类的<clinit>()方法,其他线程都需要阻塞等待,知道活动线程执行完毕。(这也说明了为什么在内存当中只有一个Class)
2.2内存分析类加载
2.3类加载时机
- 当创建一个对象(new)//静态加载
- 当子类被加载时,父类也会被加载 //静态加载
- 调用类的静态成员时 //静态加载
- 反射 //动态加载
2.4类加载器
2.4.1类加载器的作用:一句话把类(Class)装载进内存当中
将class字节码文件加载到内存当中 ,
==》并将这些静态数据转换成方法区运行时的数据结构
==》同时在堆区创建对应的class类对象,作为方法区中类数据的访问入口
2.4.2类缓存
标准的javaSE类加载器可以按要求查找类,但一旦某个类被加载类加载器当中,他将维持加载(缓存)一段时间,不过jvm垃圾回收机制(gc)可以回收这些Class对象。
2.4.3 jvm规范定义的类加载器类型
引导类加载器(跟加载器)----扩展类加载器----系统类的加载器--自定义类的加载器
/*//有哪些类加载器?
//从上往下 超累==》父类==》子类
引导类加载器(根加载器)
扩展类加载器
系统加载器()
自定义加载器
*/
public class classloader01 {
public static void main(String[] args) throws ClassNotFoundException {
//获取系统类的加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
//获取系统类的加载器的父类加载器:扩展类加载器
ClassLoader parent = systemClassLoader.getParent();
System.out.println(parent);
//获取扩展类的加载器的父类夹杂其:根类加载器
ClassLoader parent1 = parent.getParent();
System.out.println(parent1);
//获取当前类的类加载器
Class CatCls = Class.forName("com.peng.ClassLoad.ClassLoader.classloader01");
ClassLoader classLoader = CatCls.getClassLoader();
System.out.println(classLoader);
//获取jdk内置的类的类加载器
Class<?> c1 = Class.forName("java.lang.Object");
ClassLoader classLoader1 = c1.getClassLoader();
System.out.println(classLoader1);
//获取系统类的类加载器的路径
System.out.println(System.getProperty("java.class.path"));
}
}
5 通过反射获取类结构信息(涉及反射的4种主要类)
1.java.lang.class类
@Test
public void Api_01() throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
Class<?> Studentcls = Class.forName("com.peng.ClassLei.Student");
//1 getName:获取全类名
System.out.println("全类名==》"+Studentcls.getName());
//2 getSimpleName:获取简单类名
System.out.println("简单类名==》"+Studentcls.getSimpleName());
System.out.println("============================");
//3 getFields:获取所有public修饰的属性,包含本类以及父类的
Field[] fields = Studentcls.getFields();
for (Field field : fields) {
System.out.println("本类及父类的public修饰的属性==》"+field.getName());
}
//4 getDeclaredFields:获取本类的所有属性
Field[] declaredFields = Studentcls.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("本类的所有属性==》"+declaredField.getName());
}
//5*********获取指定属性的值
Field sno = Studentcls.getDeclaredField("sno");
System.out.println(sno);
System.out.println("============================");
//6 getMethods:获取所有public修饰的方法,包含本类的以及父类(超类)的
Method[] methods = Studentcls.getMethods();
for (Method method : methods) {
System.out.println("本类及父类的public修饰的方法==》"+method);
}
//7 getDeclaredMethods:获取苯类的所有方法
Method[] declaredMethods = Studentcls.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println("本类的所有方法==》"+declaredMethod);
}
//8***************获取指定方法
Method m1 = Studentcls.getDeclaredMethod("m1", String.class);
System.out.println(m1);
System.out.println("============================");
//9 getConstructors:获取本类的public修饰的构造器
Constructor<?>[] constructors = Studentcls.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("本类的public修饰的构造器==>"+constructor);
}
//10 getDeclaredConstructors:获取苯类的所有构造器
Constructor<?>[] declaredConstructors = Studentcls.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println("本类的所有构造器==>"+declaredConstructor);
}
//11 获取指定的构造器
Constructor<?> declaredConstructor = Studentcls.getDeclaredConstructor(String.class, int.class);
System.out.println(declaredConstructor);
System.out.println("============================");
//12 getPackage: 以Packgae形式返回包信息
System.out.println("返回包信息==>"+Studentcls.getPackage());
//13 getSuperClass:以Class形式返回父类信息
System.out.println("返回父类信息==>"+Studentcls.getSuperclass());
//14 getInterfaces:以Class[]形式返回接口信息
Class<?>[] interfaces = Studentcls.getInterfaces();
for (Class<?> anInterface : interfaces) {
System.out.println("Class[]形式返回接口信息==>"+anInterface);
}
System.out.println("==================================");
//15获取参数中是泛型的信息
Method test1Method = Studentcls.getMethod("test1", Map.class, List.class);
Type[] genericParameterTypes = test1Method.getGenericParameterTypes();
for (Type genericParameterType : genericParameterTypes) {
System.out.println(genericParameterType);
if (genericParameterType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("参数中是泛型的信息==>"+actualTypeArgument);
}
}
}
System.out.println("==================================");
//16获取返回值类型是泛型的信息
Method test2Method = Studentcls.getMethod("test12", null);
Type genericReturnType = test2Method.getGenericReturnType();
System.out.println(genericReturnType);
if (genericReturnType instanceof ParameterizedType){
Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
for (Type actualTypeArgument : actualTypeArguments) {
System.out.println("返回值类型是泛型的信息==>"+actualTypeArgument);
}
}
System.out.println("==================================");
//17 getAnnotations: 以Annotation[]形式返回注解信息
Annotation[] annotations = Studentcls.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println("Annotation[]形式返回注解信息==>"+annotation);
}
//18获得注解的value的值
db_table annotation1 = (db_table)Studentcls.getAnnotation(db_table.class);
String value = annotation1.value();//字段上没有这个方法
System.out.println("获得注解的value的值==>"+value);
}
2.java.lang.reflection.Field类
@Test
public void Api_02() throws ClassNotFoundException {
Class<?> Studentcls = Class.forName("com.peng.ClassLei.Student");
//4 getDeclaredFields:获取本类的所有属性
Field[] declaredFields = Studentcls.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("本类的所有属性==》"+declaredField.getName()+" 本类所有属性的修饰符权限"+declaredField.getModifiers()
+" 本类所有属性返回的的类型"+declaredField.getType());
}
}
2.java.lang.reflection.Method类
@Test
public void Api_03 () throws ClassNotFoundException {
Class<?> Studentcls = Class.forName("com.peng.ClassLei.Student");
Method[] declaredMethods = Studentcls.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println("本类的所有方法==》"+declaredMethod+" 该方法的修饰符权限==>"+declaredMethod.getModifiers()
+" 该方法的返回值类型以Class形式==》"+declaredMethod.getReturnType());
Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println("该方法的形参类型"+parameterType);
}
}
}
4.java.lang.reflection.Constructor类
//第四组接口测试 java.lang.reflection.Constructor
@Test
public void Api_04() throws ClassNotFoundException {
Class<?> Studentcls = Class.forName("com.peng.ClassLei.Student");
Constructor<?>[] declaredConstructors = Studentcls.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
System.out.println("本类的所有构造器==>"+declaredConstructor+"该构造器的修饰符权限"+declaredConstructor.getModifiers()
);
Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
for (Class<?> parameterType : parameterTypes) {
System.out.println(" 该构造器的参数类型以Class形式"+parameterType);
}
}
}
6如何动态创建一个对象(怎么反射?)
//动态创建对象执行方法 通过反射
public class DynamicallyCreateObjectsToExecuteMethods {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
}
//本质上是调用了无参构造器从而动态创建对象
@Test
public void create1() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
String classFullPath = "com.peng.pojo.User";
//获取user类的Class类对象
Class userClass = Class.forName(classFullPath);
//构造一个user对象实例
User user1 = (User) userClass.newInstance();
System.out.println(user1); //User{name='null', id=0, age=0, sex='null'}
}
//通过有参的构造器来创建对象
@Test
public void create2() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
String classFullPath="com.peng.pojo.User";
//1 获取一个user类的Class类对象
Class userClass = Class.forName(classFullPath);
//2 通过构造器来创建对象
//2.1先选择构造器
Constructor Constructor = userClass.getDeclaredConstructor(String.class, int.class, int.class, String.class);
//2.2 以构造器为对象 来newInstance
User user2 = (User) Constructor.newInstance("1号", 0001, 18, "女");
System.out.println(user2);
}
//通过反射调用普通方法 从而给其动态改变值
@Test
public void methodsAreInvokedThroughReflection() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
String classFullPath="com.peng.pojo.User";
//1 获取一个user类的Class类对象
Class userClass = Class.forName(classFullPath);
//2 创建一个User对象实例化
User user3 = (User)userClass.newInstance();
//3 通过Class类对象来获取指定的普通方法
Method setName = userClass.getDeclaredMethod("setName", String.class);
setName.invoke(user3, "3号");//invoke(对象,“方法的值”)
System.out.println(user3.getName());
}
/*//通过反射调用属性
@Test
public void fieldThroughReflection() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException {
String classFullPath="com.peng.pojo.User";
//1 获取一个user类的Class类对象
Class userClass = Class.forName(classFullPath);
//2 创建一个User对象实例化
User user4 = (User)userClass.newInstance();
//3 通过Class类对象来获取指定的字段
Field name = userClass.getDeclaredField("name");
name.set(user4,"4号");
System.out.println(user4.getName());
}
//会报错
// Class com.peng.Reflection.
// DynamicallyCreateObjectsToExecuteMethods can not access a member of class com.peng.pojo.User with modifiers "private"
//User类当中的属性是私有的 正常情况下是不能被访问的 但是在反射当中我们可以通过 setAccessible 来设置关闭 安全检查 涉及链接-验证子阶段
*/
//通过反射调用属性
@Test
public void fieldThroughReflection() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException {
String classFullPath="com.peng.pojo.User";
//1 获取一个user类的Class类对象
Class userClass = Class.forName(classFullPath);
//2 创建一个User对象实例化
User user5 = (User)userClass.newInstance();
//3 通过Class类对象来获取指定的字段
Field name = userClass.getDeclaredField("name");
//不能直接操作私有属性,需要关闭程序的安全检测,属性或者方法的setAccessible(true)
name.setAccessible(true);
name.set(user5,"5号");
System.out.println(user5.getName());
}
//会报错
// Class com.peng.Reflection.
// DynamicallyCreateObjectsToExecuteMethods can not access a member of class com.peng.pojo.User with modifiers "private"
//User类当中的属性是私有的 正常情况下是不能被访问的 但是在反射当中我们可以通过 setAccessible 来设置关闭 安全检查 涉及反射机制的性能优化
// 搞混点在于类加载-链接-验证当中有一个Xverify(none)可以关闭大部分验证 降低时间
}