反射

一、解惑

1.为什么要学习反射?

因为反射是框架设计的灵魂。了解了反射的原理,掌握了反射的用法这对后期学习框架以及手写框架能够起到很好的帮助的作用。

2.什么是反射呢?

JAVA反射机制

  • 反射就是将类的各个组成部分封装为其他对象
  • 反射机制允许我们对一个类加载,实例化,调用方法。
  • 操作属性由编译器改为运行期。提高了代码灵活度。
  • 但是运行期进行反射操作会消耗额外的资源和性能,所以要适度使用。

3.反射有什么好处和弊端呢?

  • 好处:
    (1)可以在程序运行的过程中,操作这些对象
    (2)可以解耦,提高程序的可扩展性

  • 弊端:
    (1)会存在一定的性能问题
    (2)在前期的学习中,难以理解

4.反射的应用场景举例

  • (1)反射通常用于平台或框架编程,例如:

    1. 框架中对象的构建.

    2. 框架中方法的调用.

  • (2)框架中反射应用案例分享

    1. 对象创建
      a) mybatis中的resultType,resultMap
      b) spring中的bean

    2. 方法调用
      a) 对象set方法,get方法,…
      b) spring mvc 控制层方法,…

总之:反射不能预知未来,但可驾驭未来,通过反射可以更好构建一些编程框架,以实现通用性编程,从而达到简化代码编写。

二、学习反射你需要知道的

(2.1)java代码在计算机中所经历的三个阶段

反射_第1张图片

(2.2) JVM内存中的两大对象:

在java中可以将对象分为两大体系:字节码对象实例对象

(2.2.1)如何理解字节码对象?

每个类在加载(将类从硬盘读到内存)时都会创建一个字节码对象,且这个对象在一个JVM内存中是唯一的。此对象中存储的是类的结构信息。

1) 获取Class对象的方式:

(1)Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象

应用场景:
     多用于配置文件。将类名定义在配置文件中。读取文件,加载类。

(2)类名.class:通过类名的属性class获取

应用场景:
     多用于参数的传递

(3)对象.getClass():getClass()方法在Object类中定义着

应用场景:
     多用于对象获取字节码的方式
public class reflect {
	/*
	         (1)Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
             (2)类名.class:通过类名的属性class获取
             (3)对象.getClass():getClass()方法在Object类中定义着
	 */
	
	public static void main(String[] args) throws Exception {
		//(1)Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
		Class cls1 = Class.forName("com.itcast.Person");
		System.out.println(cls1);
		//(2)类名.class:通过类名的属性class获取
		Class cls2 = Person.class;
		System.out.println(cls2);
		//(3)对象.getClass():getClass()方法在Object类中定义着
		Person p = new Person();
		Class cls3 = p.getClass();
		System.out.println(cls3);
		System.out.println(cls1==cls2);
		System.out.println(cls1==cls3);
		System.out.println(cls2==cls3);
	}
}

结论:同一个字节码文件在一次程序运行过程中,只会被加载一次,不论通过哪种方式获取的Class对象都是同一个。

(2.2.2)Class对象的功能

获取功能。

(2.2.2.1)获取成员变量

1)获取指定名称的public修饰的成员变量
Field getField(String name)

2)获取指定名称的成员变量,不考虑修饰符
Field getDeclaredField(String name)

3)获取所有public修饰的成员变量
Field[] getFields()

4)获取所有的成员变量,不考虑修饰符
Field[] getDeclaredFields()

@Test
	public void test1() throws Exception{
		Class cls1 = Class.forName("com.itcast.Person");
		Field[] fields1 = cls1.getDeclaredFields();
		for (Field field : fields1) {
			System.out.println(field);
		}
		System.out.println("******************************");
		Field[] fields2 = cls1.getFields();
		for (Field field : fields2) {
			System.out.println(field);
		}
	}

反射_第2张图片Field:成员变量
操作:
1.设置值
void set(Object obj,Object value)
2.获取值
get(Object obj)
3.忽略访问权限修饰符的安全检查
setAccessible(true):也叫暴力反射

(2.2.2.2)获取构造方法

反射_第3张图片
反射_第4张图片
Constructor:构造方法
创建对象:
如果使用空参数构造方法创建对象,操作可以简化为:
Class对象的newInstance方法
在这里插入图片描述反射_第5张图片

(2.2.2.3)获取成员方法们

反射_第6张图片反射_第7张图片
Method:方法对象
执行方法:
反射_第8张图片

(2.2.2.4)获取类名

在这里插入图片描述

(2.2.2)如何理解实例对象?

实例对象是基于类的结构信息创建的对象,在内存中可以有多份.

(2.2.2.1)实例对象的创建方式

1)编译时借助new关键字构建.(真正创建会发生在运行时)

2)运行时可借助反射API创建.

说明:每个实例对象都会独占堆内存中一块连续的内存空间.且对象的创建和销毁都会占用系统资源.

你可能感兴趣的:(反射)