JAVA反射(Reflection)
1.java为静态语言,静态语言安全()然后反射机制让JAVA成为"准动态"。
反射概念
类的加载
加载 ----链接(验证JVM规范)(准备)(解析)-----(初始)
Class加载器(JVM)
类加载器:把类加载装载进内存
-
引导类加载器:用C++,是JVM自带的类加载器,负责java平台核心库用来装载核心类库。该加载无法直接获取。
-
扩展类加载器:负责jre/lib/ext目录下的jar包或-D java.ext.dirs指定目录下的jar包装人工作库。
-
系统加载器:负责java-classpath或-D java.class.path所指定的目录下的类与jar包装入工作,常用加载器。
代码获取
//获取系统加载器 ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); System.out.println(systemClassLoader); //获取系统类加载父类 扩展加载器 ClassLoader Extension = systemClassLoader.getParent(); System.out.println(Extension); //获取扩展加载器的父类 根加载器(C++) ClassLoader Bootstap = Extension.getParent(); System.out.println(Bootstap);
打印结果
jdk.internal.loader.ClassLoaders A p p C l a s s L o a d e r @ 15 d b 9742 j d k . i n t e r n a l . l o a d e r . C l a s s L o a d e r s AppClassLoader@15db9742 jdk.internal.loader.ClassLoaders AppClassLoader@15db9742jdk.internal.loader.ClassLoadersPlatformClassLoader@3f99bd52
null
类的初始化
主动引用
- 主动引用:(一定会初始化)
- 当虚拟机启动时,先初始化mian方法
- new一个类的对象
- 调用类的静态成员(除了final常量)和静态方法
- 使用java.lang.Class反射
- 当初始化子类,如果分类没有初始化,先初始化它的父类
被动引用
-
被动引用:(不会初始化)
调用父类 引用父类的静态变量,不会导致子类初始化
数组定义引用,不会触发此类的初始化
引用常量不会初始化(常量在链接阶段就存入调用的类的常量池中了)
反射的几种方式
//1.知道类名字 ,进行反射
Class personClass = person.class;
System.out.println(personClass.hashCode());
//2.知道路径,进行反射
Class a2 = Class.forName("reflection.person");
System.out.println(a2.hashCode());
//3.通过对象反射
person a3 = new person();
Class a4 = a3.getClass();
System.out.println(a4.hashCode());
//4.获取父类类型
Class b = a2.getSuperclass();
System.out.println(b.hashCode());
System.out.println(b.toString());
类的获取
Class user = Class.forName("pojo.User");
//获取类的全名字
String name = user.getName();
//获取类名
String simpleName = user.getSimpleName();
//获取所有public方法(包括父类)
Method[] methods = user.getMethods();
//获取本类所有的方法(包括私有方法)
Method[] declaredMethods = user.getDeclaredMethods();
//获取所有的属性(不获取私有属性)
Field[] fields = user.getFields();
//获取所有属性包括私有
Field[] declaredFields = user.getDeclaredFields();
//获取构造方法
Constructor[] constructors = user.getConstructors();
//获取注解
Class user = Class.forName("pojo.User");
Annotation[] annotations = user.getAnnotations();
//获取指定注解
Aaoser annotation = (Aaoser)user.getAnnotation(Aaoser.class);
反射实例化操作
//获取对象
Class User1 = Class.forName("pojo.User");
//实例化对象
//Java9之后显示已过时 newInstance
// User u = (User)User1.newInstance();
User u1 =(User) User1.getDeclaredConstructor().newInstance();
//通过有参构造创建
Constructor declaredConstructor = User1.getDeclaredConstructor(String.class, int.class, String.class);
//创建对象
User user2 =(User) declaredConstructor.newInstance();
//通过反射获取方法(获取指定方法)
Method setName = User1.getDeclaredMethod("setName", String.class);
setName.invoke(u1,"蔡德巍");
System.out.println(u1.getName());
//设置属性
Field name = User1.getDeclaredField("name");
name.setAccessible(true);//关闭安全检查
name.set(u1,"李四");
System.out.println(u1.getName());
- getDeclaredConstructor().newInstance():获取对象
- invoke():激活方法
- setAccessible()设置安全检查 默认false
性能比较
- 普通new对象 慢
- 反射创建对象 中
- 反射关掉安全检查 快