基本功:神奇的Java反射机制了解一下

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/itsoftchenfei/article/details/87734715

在 Java中,反射机制(Reflection)非常重要,但对于很多开发者来说,这并不容易理解,在此献上一份 Java反射机制的介绍。

1. 简介

定义:Java语言中 一种 动态(运行时)访问、检测 & 修改它本身的能力

作用:动态(运行时)获取类的完整结构信息 & 调用对象的方法

2. 特点

2.1 优点

灵活性高。因为反射属于动态编译,即只有到运行时才动态创建 &获取对象实例。

编译方式说明: 
1. 静态编译:在编译时确定类型 & 绑定对象。如常见的使用new关键字创建对象 
2. 动态编译:运行时确定类型 & 绑定对象。动态编译体现了Java的灵活性、多态特性 & 降低类之间的藕合性

2.2 缺点

1. 执行效率低,因为反射的操作主要通过JVM执行,所以时间成本会 高于 直接执行相同操作。

  1. 因为接口的通用性,Java的invoke方法是传object和object[]数组的。基本类型参数需要装箱和拆箱,产生大量额外的对象和内存开销,频繁促发GC。
  2. 编译器难以对动态调用的代码提前做优化,比如方法内联。
  3. 反射需要按名检索类和方法,有一定的时间开销。

2. 容易破坏类结构 因为反射操作饶过了源码,容易干扰类原有的内部逻辑

3. 典型应用

常用的需求场景有:动态代理、工厂模式优化、Java JDBC数据库操作等

4. 实现方式

反射机制的实现主要通过 操作java.lang.Class类。

4.1 java.lang.Class

它是反射机制的基础,存放着对应类型对象的 运行时信息。

  • 在Java程序运行时,Java虚拟机为所有类型维护一个java.lang.Class对象
  • 该Class对象存放着所有关于该对象的 运行时信息
  • 泛型形式为Class<T>

每种类型的Class对象只有1个 = 地址只有1个

// 对于2个String类型对象,它们的Class对象相同
Class c1 = "Carson".getClass();
Class c2 =  Class.forName("java.lang.String");
// 用==运算符实现两个类对象地址的比较
System.out.println(c1 ==c2);
// 输出结果:true

//方式1:Object.getClass()
Boolean carson = true; 
Class<?> classType = carson.getClass(); 

// 方式2:T.class 语法
Class<?> classType = Boolean.class;    

//方式3:Class.forName
Class<?> classType = Class.forName("java.lang.Boolean");  

//方式4:TYPE语法  -->
Class<?> classType = Boolean.TYPE; 

4.2 组成部分

4.3 java.lang.reflect.Type

java.lang.reflect.Type是 Java中所有类型的父接口

4.4 访问权限问题

反射机制的默认行为受限于Java的访问控制,无法访问( private )私有的方法、字段。

冲突 Java安全机制只允许查看任意对象有哪些域,而不允许读它们的值,若强制读取,将抛出异常,怎么破?

解决方案:脱离Java程序中安全管理器的控制、屏蔽Java语言的访问检查,从而脱离访问控制。

// 作用:为反射对象设置可访问标志,flag = true时 ,表示已屏蔽Java语言的访问检查,使得可以访问 & 修改对象的私有属性
void setAccessible(boolean flag)    

// 返回反射对象的可访问标志的值
boolean isAccessible()  

// 设置对象数组可访问标志
static void setAccessible(AccessibleObject[] array, boolean flag)   

本文全面讲解了Java反射机制(Reflection)的相关知识,相信您对Java反射机制已经非常了解

猜你喜欢

转载自blog.csdn.net/itsoftchenfei/article/details/87734715