文章目录

  • 一、反射的概述
  • 二、关于Class类的理解并获取Class实例
    • 2.1 关于 java.lang.Class 类的理解
    • 2.2 获取Class实例的四种方式
  • 三、Class实例对应的结构说明
  • 四、理解类的加载过程与ClassLoader
    • 4.1 类的加载过程
    • 4.2 ClassLoader的理解

笔记来源: 尚硅谷

一、反射的概述

Reflectlon (反射) 是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。

加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象的称之为:反射。

正常方式

  1. 引入需要的包类名称
  2. 通过new实例化
  3. 取得实例化对象

反射方式:

  1. 实例化对象
  2. getClass()方法
  3. 取得完整的包类名称

java反射机制提供的功能:
➢ 在运行时判断任意一个对象所属的类
➢ 在运行时构造任意一个类的对象
➢ 在运行时判断任意一个类所具有的成员变量和方法
➢ 在运行时获取泛型信息
➢ 在运行时调用任意一个对象的成员变量和方法
➢ 在运行时处理注解
➢ 生成动态代理

首先我们看一下反射的运用:

  1. 声明一个Person实体类【有私有属性,公有属性,私有构造函数,公有构造函数,私有方法,公有方法】
public class Person { private String name; public int age; private Person(String name) { this.name = name; } public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void show() { System.out.println("我是一个人"); } private void showNation(String nation) { System.out.println("我来自"+nation); } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } }
  1. 不用反射使用Person(正常使用)
public class ReflectionTest { //反射之前对于person的操作 @Test public void Test1(){ Person person = new Person("Tom",12); person.age = 10; person.show(); System.out.println(person); //在person类外部,不可通过Person类的对象调用内部私有结构 }
}
  1. 使用反射
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.junit.Test;
public class ReflectionTest { //反射之后,对于person的对象 @Test public void Test2() throws Exception{ Class clazz = Person.class; //获取构造方法 Constructor cons = clazz.getConstructor(String.class, int.class); //使用构造方法声明一个对象 Person person = (Person) cons.newInstance("Tom",12); System.out.println(person.toString()); //获取对象指定的公有属性age,并赋值为10 Field ageField = clazz.getDeclaredField("age"); ageField.set(person, 10); System.out.println(person.toString()); //获取对象的公有方法show,并调用 Method showMethod = clazz.getDeclaredMethod("show"); showMethod.invoke(person); //通过反射调用person私有结构 //私有构造器 Constructor privateCons = clazz.getDeclaredConstructor(String.class); privateCons.setAccessible(true); Person person2 = (Person) cons.newInstance("Tom",12); System.out.println(person2.toString()); //调用私有属性 Field nameField = clazz.getDeclaredField("name"); nameField.setAccessible(true); nameField.set(person2, "Peter"); //调用私有方法showNation Method showNationMethod = clazz.getDeclaredMethod("showNation", String.class); showNationMethod.setAccessible(true); showNationMethod.invoke(person2, "中国"); System.out.println(person2.toString()); }
}

输出结果为:

Person [name=Tom, age=12]
Person [name=Tom, age=10]
我是一个人
Person [name=Tom, age=12]
我来自中国
Person [name=Peter, age=12]

综上所述,反射的强大之处在于可以调用一个类的私有结构

疑问:

  1. 有了反射以后,与面向对象的封装性是不是矛盾的?

答:不矛盾。封装性可以看做一种提示,提示你公有方法可以调用,私有方法最好不要调用,而反射解决的是能不能调用的问题

  1. 通过直接new对象,还是通过反射调用公共结构,开发中用哪个?

答:建议使用直接new的方式。
反射的特征:动态性。在动态执行代码,不确定new谁的时候,使用反射。


二、关于Class类的理解并获取Class实例

Class clazz = Person.class;

2.1 关于 java.lang.Class 类的理解

  1. 类的加载过程:

程序在编译后会生成一个或多个字节码文件(.class结尾),接着我们使用java.exe命令对某个字节码文件解释运行,相当于将某个字节码文件加载到内存中,此过程就叫做 类的加载 ,加载到内存的类,就成为运行时类,这个运行时类,就是Class的一个实例

  1. 换句话说,Class的实例就对应着一个运行时的类
  2. 加载到内存中的运行时类,会缓存一段时间,在此时间内,我们可以通过不同的方式获取此运行时类

2.2 获取Class实例的四种方式

  1. 方式一:调用运行时类的属性.class
Class<Person> clazz = Person.class;
  1. 方式二:通过运行时类的对象
Person person = new Person("tom", 12);
Class clazz1 = person.getClass();
  1. 方式三:调用class的静态方法:forName(String classPath)
Class clazz2 = Class.forName("reflection.Person");

我们判断一下三个对象的地址是否相同(是否指向同一个运行时类):

System.out.println(clazz==clazz1);
System.out.println(clazz1==clazz2);

运行结果:

true
true

  1. 方法四:使用类加载器ClassLoader
ClassLoader classLoader=ReflectionTest.class.getClassLoader();
Class clazz4 = classLoader.loadClass("reflection.Person");
System.out.println(clazz==clazz4);

true

方法三用得最多


三、Class实例对应的结构说明

哪些类型可以有Class对象?

(1) class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
(2) interface:接口
(3) []:数组
(4) enum:枚举
(5) annotation:注解@interface
(6) primitive type:基本数据类型
(7) void

@Test
public void test4(){ Class c1 = object.class; Class c2 = Comparable.class; Class c3 = String[].class; Class c4 = int[][].class; Class c5 = ElementType.class; Class c6 = Override.class; Class c7 = int.class; Class c8 = void.class; Class c9 = Class.class; int[] a = new int[10]; int[] b = new int[100] ; Class c10 = a.getClass(); Class c11 = b.getClass(); //只要数组类型与维度一样,就是同一个Class System.out.print1n(c10 == c11);
}

四、理解类的加载过程与ClassLoader

4.1 类的加载过程

当程序主动使用某个类时,如果该类还未被加载到内存中,则系统会通过如下三个步骤来对该类进行初始化。

加载 :将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口(即引用地址)。所有需要访问和使用类数据只能通过这个Class对象。这个加载的过程需要类加载器参与。
链接 :将Java类的二进制代码合并到JVM的运行状态之中的过程。
➢ 验证:确保加载的类信息符合JVM规范,例如:以cafe开头,没有安全方面的问题
➢ 准备:正式为类变量(static )分配内存并设置类变量 默认初始值 的阶段,这些内存都将方法区中进行分配。
➢ 解析: 虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程。
初始化:
➢ 执行类构造器()方法的过程。类构造器()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。(类构造器是构造类信息的,不是构造该类对象的构造器)。
➢ 当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化。
➢ 虚拟机会保证一个类的()方法在多线程环境中被正确加锁和同步。

我们以下面这个实例说明:

public class ClassLoadingTest { public static void main(String[] args) { System.out.println(A.m); }
}
class A{ static { m = 300; } static int m = 100;
}

4.2 ClassLoader的理解

类加载器的作用:

  • 类加载的作用:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口。

  • 类缓存:标准的JavaSE 类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间。不过JVM垃圾回收机制可以回收这些Class对象

import org.junit.Test;
public class ClassLoaderTest { @Test public void test1(){ //对于自定义类,使用系统类加载器进行加载 //获取当前类加载器【系统类加载器】 ClassLoader classLoader = ClassLoaderTest.class.getClassLoader(); System.out.println(classLoader); //获取系统类加载器的父类:扩展类加载器 ClassLoader classLoader1 = classLoader.getParent(); System.out.println(classLoader1); //引导类加载器【主要负责加载JAVA核心类库】无法用getParent获取 }
}

sun.misc.Launcher$AppClassLoader@5c647e05

sun.misc.Launcher$ExtClassLoader@330bedb4

java 反射机制及其应用相关推荐

  1. 利用java反射机制 读取配置文件 实现动态类载入以及动态类型转换

    作者:54dabang 在spring的学习过程之中,我们能够看出通过配置文件来动态管理bean对象的优点(松耦合 能够让零散部分组成一个总体,而这些总体并不在意之间彼此的细节,从而达到了真正的物理上 ...

  2. Struts2中action接收参数的三种方法及ModelDriven跟Preparable接口结合JAVA反射机制的灵活用法...

    Struts2中action接收参数的三种方法及ModelDriven跟Preparable接口结合JAVA反射机制的灵活用法 www.MyException.Cn   发布于:2012-09-15 ...

  3. Java反射机制分析指南

    一.JAVA是动态语言吗? 一般而言,说到动态言,都是指在程序运行时允许改变程序结构或者变量类型,从这个观点看,JAVA和C++一样,都不是动态语言. 但JAVA它却有着一个非常突出的动态相关机制:反 ...

  4. 反射 字段_详解面试中常考的 Java 反射机制

    反射(Reflection) 是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说"自审",并能直接操作程序的内部属性和方法. 反射是一项高级 ...

  5. 【java】java反射机制,动态获取对象的属性和对应的参数值,并属性按照字典序排序,Field.setAccessible()方法的说明【可用于微信支付 签名生成】...

    方法1:通过get()方法获取属性值 package com.sxd.test.controller;public class FirstCa{private Integer num;private ...

  6. java基础-java反射机制

    2019独角兽企业重金招聘Python工程师标准>>> 引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓"登高必自卑,涉远必自迩" ...

  7. 利用java反射机制进行对象操作

    我们经常使用COMMONS-BEANUTILS包来进行bean的操作,例如从map到bean获从bean到map的映射,那么实现的原理是什么呢,下面举个简单的操作的例子:首先,我建立一个bean pu ...

  8. java反射机制知识_Java反射机制讲解,程序员必须掌握的知识点

    关注程序员7歌,一起用技术改变世界 大家好,我是程序员7歌,今天我为大家讲解Java的反射机制. 首先我们来看看反射的概念: Java反射说的就是在程序运行中,任何一个类,我们都可以知道这个类的方法和 ...

  9. java继承 映射_hibernate继承关系映射和java反射机制的运用

    转:http://blog.csdn.net/derpvailzhangfan/article/details/1957946 ,感谢博主分享 Notes:hibernate元数据的运用:uuid的概 ...

  10. java初反射_初始 java 反射机制 (一)

    反射机制详解 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为j ...

最新文章

  1. JUC包中的分而治之策略-为提高性能而生
  2. java short字段_Java Field setShort()用法及代码示例
  3. 性能分析工具 Android TraceView
  4. Java应用全链路启动速度提升至15s,阿里云SAE能力再升级
  5. 各种ABAP调用的性能比较,附详细参数
  6. Hibernate4之session核心方法
  7. 文科生能学懂python吗_文科生也能学得懂的Python入门视频
  8. 图灵测试是什么?为什么AlphaGo那么牛却过不了?
  9. 深圳 | 鹏程实验室研究员招收访问学生
  10. 学习easyui疑问(三)
  11. CSS属性小结之--半透明处理
  12. group by 分组
  13. 6_Selenium Excel参数化
  14. windows下杀死关不掉的进程
  15. Python使用struct处理二进制(pack和unpack用法)
  16. ajax的get json数据格式,jQuery / 用getJSON()方法加载JSON格式数据 - 汇智网
  17. libreoffice7.0 离线安装
  18. 中国参与MOOC 建设的大学有多少所?
  19. Centos7命令行方式安装DM
  20. c语言 inc文件夹,汇编 inc 和 dec 指令

热门文章

  1. python练手经典100例-10 个最值得 Python 新人练手的有趣项目
  2. python基础教程是什么-python基础教程都有什么?
  3. 5岁儿童自学python编程-小孩子如何学python?
  4. html鼠标感应图片,jQuery实现的感应鼠标悬停图片色彩渐显效果
  5. 什么是pdi检测_汽车pdi检测是什么?如何知道新车做没做pdi
  6. 计算机信息安全技术计算题,计算机信息安全技术练习题.doc
  7. html图片使用glide,jQuery响应式幻灯片插件jquery.glide.js(支持触摸轻量级)
  8. mysql 修复数据表 批量_MySQL数据库迁移与MySQL数据库批量恢复
  9. mysql进程线程_MySQL 内核线程简要分析
  10. C# 正则匹配 电话号码 和 座机号