反射

反射机制

1、允许程序在执行期间借助 Reflection API 取得任何类的内部消息

2、加载完类之后,在堆中产生一个 Class 类型对象

3、一个类只有一个 Class 对象,该对象包含类的完整结构信息

 

反射相关的类

1、java.lang.Class<T>:Class 对象表示某个类加载后在堆中的对象

2、java.lang.reflect.Method:Method 对象表示某个类的方法

3、java.lang.reflect.Field:Field 对象表示某个类的成员变量

4、java.lang.reflect.Constructor<T>:Constructor 对象表示某个类的构造器

 

反射暴破

1、反射调用优化:关闭访问检查,提高反射效率

2、Method、Field、Constructor 继承 AccessibleObject,AccessibleObject 定义 setAccessible 方法

3、将调用方法的对象的 accessible 标志设置为指定的 boolean 值,true 表示反射对象应该在使用时抑制 Java 语言访问检查,false 表示反射的对象应该强制执行 Java 语言访问检查

public void setAccessible(boolean flag) throws SecurityException

 

Class 类

1、继承 Object 类,该类对象是系统通过类加载器(Classloader 类)的 loadClass 方法创建

2、类只加载一次,所以堆中类的 Class 对象只有一个

3、每个类的对象都知道自身属于哪个 Class 类对象生成的

4、通过 Class 对象的 API 得到一个类的完整结构

5、类的字节码(.class)二进制数据(类的元数据)储存在方法区

 

获取 Class 类对象

1、已知一个类的全类名,且该类在类路径下,通过 Class 类的静态方法 forName 获取

Class cls = Class.forName("类的全类名");

(1)应用场景:配置文件读取类的全路径,加载类

2、已知具体的类,通过该类的 class 获取

Class cls = 类名.class;

(1)最安全,性能最高

(2)应用场景:用于传递参数

3、已知某个类的实例,调用该实例的 getClass 方法获取

Class cls = 对象名.getClass();

(1)应用场景:通过已创建的对象,获取 Class 对象

4、通过类的加载器获取

ClassLoader classLoader = 对象名.getClass().getClassLoader();
Class cls = classLoader.loadClass("类的全类名");

5、基本数据类型、包装类获取的 Class 对象是同一个,因为有自动装箱、拆箱机制

(1)基本数据类型

Class<包装类> cls = 基本数据类型.class;

(2)包装类

Class<包装类> cls = 包装类.TYPE;

 

存在 Class 对象的类型

1、外部类

2、成员内部类、静态内部类、局部内部类、匿名内部类

3、interface 接口、数组、annotation 注解、enum 枚举、基本数据类型、Class、void

 

类加载

1、静态加载:编译阶段加载相关类,若不存在该类,依赖性强

2、动态加载:运行阶段加载相关类,若运行阶段时不调用此类,则不报错,降低依赖性

3、类加载时机:静态加载:(1)(2)(3);动态加载:(4)

(1)创建对象

(2)子类被加载,父类也加载

(3)调用类中的静态成员(static final 不会导致类加载)

(4)通过反射

 

.java 源文件 ->(javac 编译)-> .class 字节码文件 ->(java 运行)-> 加载 -> 连接:验证、准备、解析 -> 初始化

1、加载:由类加载器完成,字节码从不同数据源转为二进制字节流加载到内存,字节码文件储存在方法区,创建 Class 对象储存在堆

2、连接:类的二进制数据合并到 JRE中

(1)验证:确保 .class 文件字节流所含信息符合当前虚拟机的要求,且不危害虚拟机自身安全;文件格式验证、元数据验证、字节码验证、、符号引用验证;可以使用 -Xvertify:none 参数关闭大部分类验证措施,缩短虚拟机加载时间

(2)准备:JVM 对静态变量、分配内存并默认初始化(数据类型的默认初始值),在方法区分配所使用的内存

(3)解析:虚拟机将常量池内符号引用替换为直接引用

3、初始化:执行 <clinit>() 方法,真正执行类中定义的 Java 程序代码

(1)<clinit>() 方法由编译器按语句在源文件出现顺序,依次自动收集类中所有静态变量赋值动作、静态代码块中语句,并合并

(2)虚拟机保证一个类的 <clinit>() 方法在多线程环境中被正确的加锁、同步

(3)若多线程同时初始化一个类,只有一个线程执行该类 <clinit>() 方法,其他线程阻塞,直到活动线程执行完毕

 

Modifier 类

public static final int PUBLIC           = 0x00000001;
public static final int PRIVATE          = 0x00000002;
public static final int PROTECTED        = 0x00000004;
public static final int STATIC           = 0x00000008;
public static final int FINAL            = 0x00000010;
public static final int SYNCHRONIZED     = 0x00000020;
public static final int VOLATILE         = 0x00000040;
public static final int TRANSIENT        = 0x00000080;
public static final int NATIVE           = 0x00000100;
public static final int INTERFACE        = 0x00000200;
public static final int ABSTRACT         = 0x00000400;
public static final int STRICT           = 0x00000800;
static final int BRIDGE    = 0x00000040;
static final int VARARGS   = 0x00000080;
static final int SYNTHETIC = 0x00001000;
static final int ANNOTATION  = 0x00002000;
static final int ENUM      = 0x00004000;
static final int MANDATED  = 0x00008000;

 

通过反射获取类的结构信息

1、Class 类

(1)返回指定注释类型的注释,包含继承的注解,若此注解类型不存在,返回 null

public <A extends Annotation> A getAnnotation(Class<A> annotationClass)

(2)以数组形式返回所有注释,包含继承的注解

public Annotation[] getAnnotations()

(3)返回一个 Class 数组,包含本类及父类的所有 public 内部类和接口的 Class 对象,若为基本数据类型、数组、void、此类对象没有 public 类或接口,则返回长度为 0 的数组

public Class<?>[] getClasses()

(4)返回类的类加载器

public ClassLoader getClassLoader()

(5)根据参数类型,返回本类的 public 构造器 Consrtructor 对象

public Constructor<T> getConstructor(类<?>... parameterTypes) throws NoSuchMethodException, SecurityException

(6)返回一个包含 Constructor 对象的数组,包含本类的所有 public 类函数,若为基本数据类型、数组、void、此类对象没有 public 构造器,返回长度为 0 的数组

public Constructor<?>[] getConstructors() throws SecurityException

(7)返回指定注释类型的注释,不包含继承的注解,若此注解类型不存在,返回 null

public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass)

(8)以数组形式返回所有注释,不包含继承的注解

public Annotation[] getDeclaredAnnotations()

(9)返回一个 Class 数组,包含本类所有内部类和接口的 Class 对象,若为基本数据类型、数组、void、此类对象没有 public 类或接口,则返回长度为 0 的数组

public Class<?>[] getDeclaredClasses() throws SecurityException

(10)返回指定参数类型的  Consrtructor 对象

public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException

(11)返回所有构造器 Consrtructor 对象数组

public Constructor<?>[] getDeclaredConstructors() throws SecurityException

(12)返回指定 name 的 Field 对象

public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException

(13)返回本类所有属性 Field 对象数组,如果此类对象没有声明字段、数组、基本数据类型、void,则此方法返回长度为0的数组

public Field[] getDeclaredFields() throws SecurityException

(14)根据指定的名称和参数,返回本类 Method 对象

public Method getDeclaredMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException

(15)返回本类所有方法 Method 对象数组

public Method[] getDeclaredMethods() throws SecurityException

(16)返回该类的外部类 Class 对象,若不为内部类、或为匿名内部类、数组、基本数据类型、void,返回 null

public Class<?> getDeclaringClass() throws SecurityException

(17)返回该类的外部类 Class 对象,若该类是顶级类,则此方法返回 null

public Class<?> getEnclosingClass() throws SecurityException

(18)返回该内部类的 Constructor 对象,若不为内部类,返回 null

public Constructor<?> getEnclosingConstructor() throws SecurityException

(19)返回该内部类的 Method 对象,若不为内部类,返回 null

public Method getEnclosingMethod() throws SecurityException

(20)返回此枚举类的元素数组,如果此 Class 对象不表示枚举类型,则返回null

public T[] getEnumConstants()

(21)返回指定 name 的一个 Field 对象,包括本类及父类的 public 属性

public Field getField(String name) throws NoSuchFieldException, SecurityException

(22)返回 Field 对象数组,包括本类及父类的所有 public 属性

public Field[] getFields() throws SecurityException

(23) 返回此 Class 对象表示的类或接口直接实现的接口的 Type 数组

public Type[] getGenericInterfaces()

(24)返回该 Class 对象直接父类的 Type,若为 Object类、接口、基本数据类型、void,则返回 null,若为数组,则返回 Object 类的 Class 对象

public Type getGenericSuperclass()

(25)返回此 Class 对象表示的类或接口实现的接口 Class 对象数组

public Class<?>[] getInterfaces()

(26)根据 name、参数类型,返回 Method 对象,限本类及父类所有 public 方法

public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException

(27)返回 Method 对象数组,包含本类及父类所有 public 方法

public Method[] getMethods() throws SecurityException

(28)返回全类名

public String getName()

(29)返回包名

public Package getPackage()

(30)返回简单类名

public String getSimpleName()

(31)返回该 Class 对象直接父类的 Type,若为 Object类、接口、基本数据类型、void,则返回 null,若为数组,则返回 Object 类的 Class 对象

public Class<? super T> getSuperclass()

(32)以 int 形式返回修饰符,多个修饰符则相加

public int getModifiers()

2、Field 类

(1)返回属性名

public String getName()

(2)返回属性类型的 Class 对象

public Class<?> getType()

(3)以 int 形式返回修饰符,多个修饰符则相加

public int getModifiers()

3、Method 类

(1)返回方法名

public String getName()

(2)以 int 形式返回修饰符,多个修饰符则相加

public int getModifiers()

(3)获取方法返回数据类型的 Class 对象

public Class<?> getReturnType()

(4)返回方法的形参 Class 对象数组,以声明顺序排序,若没有参数,则返回长度为 0 的数组

public Class<?>[] getParameterTypes()

4、Constructor 类

(1)返回此构造函数的名称

public String getName()

(2)以 int 形式返回修饰符,多个修饰符则相加

public int getModifiers()

(3)返回构造器的形参 Class 对象数组,以声明顺序排序,若没有参数,则返回长度为 0 的数组

public Class<?>[] getParameterTypes()

 

通过反射创建对象

1、调用 Class 类中方法

(1)调用类中无参构造器,获取对应类的对象,要求构造器为 public

Class对象.newInstance();

(2)根据参数的 Class 对象,获取 public 构造器

public Constructor<T> getConstructor(Class<?>... parameterTypes)

(3)根据参数的 Class 对象,获取构造器

public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)

2、调用 Constructor 类中方法

(1)暴破构造器的封装性,即可以调用 private 构造器

Constructor对象.setAccessible(true);

(2)根据参数列表创建对象,若没有暴破,则要求为 public 构造器

Constructor对象.newInstance(参数列表);

 

通过反射访问属性

1、暴破

Field对象.setAccessible(true);

2、设置属性:将 obj 对象的属性(该 Field 对象)设为 value

public void set(Object obj, Object value) throws IllegalArgumentException, IllegalAccessException

3、获取属性:返回 obj 对象的属性(该 Field 对象)

public Object get(Object obj) throws IllegalArgumentException, IllegalAccessException

4、若属性为 static,set、get 方法中的 obj 参数传入 null

 

通过反射访问方法

1、暴破

Method对象.setAccessible(true);

2、访问方法:传入 args 参数,调用 obj 对象的方法(该 Method 对象)

public Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException

(1)若为 static 方法,obj 参数传入 null

(2)若方法存在返回值,编译类型为 Object,运行类型与方法定义的返回数据类型一致

posted @   半条咸鱼  阅读(29)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示