阿里云的网站接入方式网站空间 群集
阿里云的网站接入方式,网站空间 群集,网站建设与管理的主要内容,可以设计制作网页的软件反射 反射的概念
反射机制允许程序在执行期借助于ReflectionAPI取得任何类的内部信息(比如成员变量#xff0c;构造器#xff0c;成员方法等等)#xff0c;并能操作对象的属性及方法。反射在设计模式和框架底层都会用到加载完类之后#xff0c;在堆中就产生了一个Class类型…
反射 反射的概念
反射机制允许程序在执行期借助于ReflectionAPI取得任何类的内部信息(比如成员变量构造器成员方法等等)并能操作对象的属性及方法。反射在设计模式和框架底层都会用到加载完类之后在堆中就产生了一个Class类型的对象(一个类只有一个Class对象)这个对象包含了类的完整结构信息。通过这个对象得到类的结构。这个对象就像一面镜子透过这个镜子看到类的结构所以形象的称之为反射 反射机制
Java反射机制可以完成
在运行时判断任意一个对象所属的类在运行时构造任意一个类的对象在运行时得到任意一个类所具有的成员变量和方法在运行时调用任意一个对象的成员变量和方法生成动态代理 反射相关的主要类:
java.lang.Class:代表一个类Class对象表示某个类加载后在堆中的对象java.lang.reflect.Method: 代表类的方法java.lang.reflect.Field: 代表类的成员变量java.lang.reflect.Constructor: 代表类的构造方法
一般使用对象.方法 反射使用方法.对象一般使用对象.变量 反射使用变量.对象 反射优点和缺点
**优点**可以动态的创建和使用对象(也是框架底层核心)使用灵活,没有反射机制框架技术就失去底层支撑。**缺点**使用反射基本是解释执行,对执行速度有影响, 反射调用优化-关闭访问检查
Method和Field、Constructor对象都有setAccessible()方法setAccessible作用是启动和禁用访问安全检查的开关。默认为false
参数值为true表示反射的对象在使用时取消访问检查提高反射的效率。参数值为false表示反射的对象执行访问检查 Class类
Class也是类因此也继承Object类 Class类对象不是new出来的而是系统创建的对于某个类的Class类对象在内存中只有一份因为类只加载一次以hashcode区别使用synchronized同步每个类的实例都会记得自己是由哪个 Class 实例所生成通过Class对象可以完整地得到一个类的完整结构,通过一系列APIClass对象是存放在堆的类的字节码二进制数据是放在方法区的 有的地方称为类的元数据(包括 方法代码变量名方法名访问权限等等)https://www.zhihu.com/question/38496907 Class类的常用方法:
java.lang.Class
getName获取全类名getSimpleName获取简单类名getFields获取所有public修饰的属性包含本类以及父类的getDeclaredFields获取本类中所有属性getMethods获取所有public修饰的方法包含本类以及父类的getDeclaredMethods获取本类中所有方法getConstructors 获取本类所有public修饰的构造器getDeclaredConstructors获取本类中所有构造器getPackage以Package形式返回 包信息getsuperClass以Class形式返回父类信息getlnterfaces以Class[]形式返回接口信息getAnnotations以Annotation[] 形式返回注解信息 获取Class对象的几种方式
代码阶段Class.forName()
前提已知一个类的全类名且该类在类路径下可通过Class类的静态方法forName()获取可能抛出ClassNotFoundException例Class clazz Class.forName( java.lang.Cat”);应用场景:多用于配置文件读取类全路径加载类
Class类阶段类.class
前提若已知具体的类通过类的class 获取该方式最为安全可靠程序性能最高应用场景多用于参数传递比如通过反射得到对应构造器对象
Runtime阶段对象.getClass()
前提已知某个类的实例调用该实例的getClass()方法获取Class对象例Class clazz object.qetClass();应用场景通过创建好的对象获取Class对象
其他方式类加载器
ClassLoader classLoader object.getClass().getClassLoader();Class clazz classLoader.loadClass(类的全类名);
基本数据(int, char,boolean,float,double,byte,long,short) 按如下方式得到Class类对象
Class clazz 基本数据类型.class;
基本数据类型对应的包装类可以通过.type 得到Class类对象
Class clazz 包装类.TYPE; 以下类型有Class对象
外部类成员内部类静态内部类局部内部类匿名内部类interface接口数组enum枚举annotation注解最本基本数据类型void 类加载 基本说明
反射机制是java实现动态语言的关键也就是通过反射实现类动态加载。
静态加载编译时加载相关的类如果没有则报错依赖性太强动态加载运行时加载需要的类如果运行时不用该类则不报错降低了依赖性 类加载时机
创建类的实例属于静态加载。当使用 new 关键字创建一个类的实例时该类会被加载、连接和初始化这是在编译期就确定需要加载的类。访问类的静态变量属于静态加载。当访问一个类的静态变量static field时如果该类还没有加载则会触发类的加载、连接和初始化这也是在编译期就确定需要加载的类。调用类的静态方法属于静态加载。当调用一个类的静态方法时如果该类还没有加载则会触发类的加载、连接和初始化同样是在编译期确定需要加载的类。访问类的静态字段的值属于静态加载。当访问一个类的静态字段的值static final field时不会触发类的初始化因为这些字段在编译期就会被赋值。使用反射属于动态加载。通过反射机制来创建类的实例、访问类的静态变量或调用类的静态方法时是在程序运行时根据需要动态加载类。 类加载过程
类加载各阶段完成任务前两个阶段在JVM中
加载阶段Loading
加载阶段是指查找并加载类的字节码文件.class 文件一般是通过类加载器ClassLoader来完成的。类加载器根据类的全限定名在类路径中查找对应的字节码文件并将其加载到内存中。 链接阶段Linking-验证
验证确保被加载的类符合 Java 虚拟机规范比如检查字节码的格式、语义等。目的是为了确保 Class 文件的字节流中包含的信息符合当前虚拟机的要求并且不会危害虚拟机自身的安全。包括文件格式验证(是否以魔数 oxçafebabe开头)、元数据验证、字节码验证和符号引用验证。可以考虑使用 -Xverify:none 参数来关闭大部分的类验证措施缩短虚拟机类加载的时间。 链接阶段Linking-准备
JVM 会在该阶段对静态变量分配内存并默认初始化对应数据类型的默认初始值如 0、0L、null、false等。这些变量所使用的内存都将在方法区中进行分配 链接阶段Linking-解析
虚拟机将常量池内的符号引用转换为直接引用比如将类、方法、字段等的符号引用解析为实际内存地址 初始化Initialization
到初始化阶段才真正开始执行类中定义的 Java 程序代码此阶段是执行()方法的过程。()方法是由编译器按语句在源文件中出现的顺序依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并进行合并。类初始化是按需进行的只有在首次主动使用类时才会触发。虚拟机会保证一个类的()方法在多线程环境中被正确地加锁、同步如果多个线程同时去初始化一个类那么只会有一个线程去执行这个类的()方法其他线程都需要阻塞等待直到活动线程执行()方法完毕 通过反射获取类的结构 通过反射创建对象
方式一调用类中的public修饰的无参构造器方式二调用类中的指定构造器Class类相关方法 newlnstance调用类中的无参构造器获取对应类的对象getConstructor(Class…clazz)根据参数列表获取对应的构造器对象getDecalaredConstructor(Class…clazz)根据参数列表获取对应的构造器对象 Constructor类相关方法 setAccessible()参数使用true暴破使用反射可以访问私有private构造器/属性/方法newlnstance(Object…obj)调用构造器
package com.gg
class abc{puiblic String name ;abc(String name){this.name name ;}
}
Class? clazz Class.forName(com.gg.abc);
Object o clazz.newInstance(); // 调用无参构造 o的运行对象类型为abc类Constructor? c clazz.getDecalaredConstructor(String.class);//调用有参构造
Object o1 c.newInstance(gggg); // o1的运行对象类型为abc类 通过反射访问类中的成员
根据方法名和参数列表获取Method方法对象Method m clazz.getDeclaredMethod(方法名XX.class);获取对象Object o clazz.newInstance();暴破m.setAccessible(true);访问Object returnValue m.invoke(o,实参列表); //o表示对象注意如果是静态方法则invoke的参数o可以写成null如果方法有返回值统一返回Object但其运行类型依旧是方法中定义的返回类型
package com.gg
class abc{puiblic String name ;abc(String name){this.name name ;}public void aabc(String name){System.out.println(name this.name);}
}
// 获取Class对象
Class? clazz Class.forName(com.gg.abc);
//调用有参构造
Constructor? c clazz.getDecalaredConstructor(String.class);
// o1的运行对象类型为abc类
Object o1 c.newInstance(gggg);
// 获取aabc方法对象
Method m clazz.getDeclaredMethod(aabc,String.class);
// 反射调用aabc方法
Object res m.invoke(o1,aaaa);
// 输出 aaaa gggg通过反射访问类中的属性
根据属性名获取Field对象Field f clazz.getDeclaredField(属性名);暴破 f.setAccessible(true); // f 是Field 访问 f.set(o,值);// o表示对象f.get(o); //o表示对象 注意如果是静态属性则set和get中的参数o可以写成null
package com.gg
class abc{puiblic String name ;abc(String name){this.name name ;}public void aabc(String name){System.out.println(name this.name);}
}
// 获取Class对象
Class? clazz Class.forName(com.gg.abc);
//调用有参构造
Constructor? c clazz.getDecalaredConstructor(String.class);
// o1的运行对象类型为abc类
Object o1 c.newInstance(gggg); //此时namegggg
// 获取name属性对象
Field f clazz.getDeclaredField(name);
// 设置name属性的值
f.set(o1,123);// 此时name123
// 获取并输出name属性值
System.out.println(f.get(o1));
// 输出 123Field类常用方法
java.lang.reflect.Field
getModifiers以int形式返回修饰符、 [说明默认修饰符 是0 public 是1private 是2protected 是 4static是8final是16]public static public(1) static(8) 1 8 9 getType以Class形式返回类型getName返回属性名 Method类常用方法
java.lang.reflect.Method
getModifiers以int形式返回修饰符 [说明默认修饰符 是0 public 是1private 是2protected 是 4static是8final是16] getReturnType以Class形式获取 返回类型getName返回方法名getParameterTypes以Class[ ]返回参数类型数组 Constructor类常用方法
java.lang.reflect.Constructor
getModifiers以int形式返回修饰符getName返回构造器名(全类名)getParameterTypes以Class[ ]返回参数类型数组
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/91932.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!