首页 > 其他分享 >反射机制

反射机制

时间:2024-01-14 16:44:47浏览次数:23  
标签:反射 调用 class 机制 时类 Class 加载

01-反射的举例

通过使用反射前后的例子的对比,回答:

1. 面向对象中创建对象,调用指定结构(属性、方法)等功能,可以不使用反射,也可以使用反射。请问有什么区别?

不使用反射,我们需要考虑封装性。比如:出了Person类之后,就不能调用Person类中私有的结构
使用反射,我们可以调用运行时类中任意的构造器、属性、方法。包括了私有的属性、方法、构造器。


2. 以前创建对象并调用方法的方式,与现在通过反射创建对象并调用方法的方式对比的话,哪种用的多?
   场景是什么?

> 从我们作为程序员开发者的角度来讲,我们开发中主要是完成业务代码,对于相关的对象、方法的调用都是确定的。
  所以,我们使用非反射的方式多一些。

> 因为反射体现了动态性(可以在运行时动态的获取对象所属的类,动态的调用相关的方法),所以我们在设计框架的时候,
  会大量的使用反射。意味着,如果大家需要学习框架源码,那么就需要学习反射。

  框架 = 注解 + 反射 + 设计模式

3. 单例模式的饿汉式和懒汉式中,私有化类的构造器了! 此时通过反射,可以创建单例模式中类的多个对象吗?

是的!


4. 通过反射,可以调用类中私有的结构,是否与面向对象的封装性有冲突?是不是Java语言设计存在Bug?

不存在bug!

封装性:体现的是是否建议我们调用内部api的问题。比如,private声明的结构,意味着不建议调用。
反射:体现的是我们能否调用的问题。因为类的完整结构都加载到了内存中,所有我们就有能力进行调用。

02-Class的理解与类的加载

1. Class类的理解(掌握)
(如下以Java类的加载为例说明)
针对于编写好的.java源文件进行编译(使用javac.exe),会生成一个或多个.class字节码文件。接着,我们使用
java.exe命令对指定的.class文件进行解释运行。这个解释运行的过程中,我们需要将.class字节码文件加载(使用类的加载器)
到内存中(存放在方法区)。加载到内存中的.class文件对应的结构即为Class的一个实例。

比如:加载到内存中的Person类或String类或User类,都作为Class的一个一个的实例

Class clazz1 = Person.class;  //运行时类
Class clazz2 = String.class;
Class clazz3 = User.class;
Class clazz4 = Comparable.class;

说明:运行时类在内存中会缓存起来,在整个执行期间,只会加载一次。

2. 体会:Class看做是反射的源头

3. 获取Class实例的几种方式(掌握前三种)
见代码


4. Class的实例都可以指向哪些结构呢?(熟悉)
简言之,所有Java类型!
(1)class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类
(2)interface:接口
(3)[]:数组
(4)enum:枚举
(5)annotation:注解@interface
(6)primitive type:基本数据类型
(7)void



5. 类的加载过程(了解)
过程1:类的装载(loading)
将类的class文件读入内存,并为之创建一个java.lang.Class对象。此过程由类加载器完成

过程2:链接(linking)
> 验证(Verify):确保加载的类信息符合JVM规范,例如:以cafebabe开头,没有安全方面的问题。
> 准备(Prepare):正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配。
> 解析(Resolve):虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程。

过程3:初始化(initialization)
执行类构造器<clinit>()方法的过程。
类构造器<clinit>()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。



5. 关于类的加载器(了解、JDK8版本为例)
5.1 作用:负责类的加载,并对应于一个Class的实例。

5.2 分类(分为两种):
> BootstrapClassLoader:引导类加载器、启动类加载器
     > 使用C/C++语言编写的,不能通过Java代码获取其实例
     > 负责加载Java的核心库(JAVA_HOME/jre/lib/rt.jar或sun.boot.class.path路径下的内容)

> 继承于ClassLoader的类加载器
    > ExtensionClassLoader:扩展类加载器
            > 负责加载从java.ext.dirs系统属性所指定的目录中加载类库,或从JDK的安装目录的jre/lib/ext子目录下加载类库
    > SystemClassLoader/ApplicationClassLoader:系统类加载器、应用程序类加载器
            > 我们自定义的类,默认使用的类的加载器。
    > 用户自定义类的加载器
            > 实现应用的隔离(同一个类在一个应用程序中可以加载多份);数据的加密。

5.3 以上的类的加载器是否存在继承关系? No!

class ClassLoader{
    ClassLoader parent;

    public ClassLoader(ClassLoader parent){
        this.parent = parent;
    }
}


//测试代码:
ClassLoader loader0 = new ClassLoader();
ClassLoader loader1 = new ClassLoader(loader0);
我们就把loader0叫做loader1的父类加载器。

6. (掌握)使用类的加载器获取流,并读取配置文件信息
/*
* 需求:通过ClassLoader加载指定的配置文件
* */
@Test
public void test3() throws IOException {
    Properties pros = new Properties();

    //通过类的加载器读取的文件的默认的路径为:当前module下的src下
    InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("info1.properties");

    pros.load(is);

    String name = pros.getProperty("name");
    String pwd = pros.getProperty("password");
    System.out.println(name + ":" +pwd);
}

03-反射的应用

1. (掌握)反射的应用1:创建运行时类的对象
1.1 如何实现?
通过Class的实例调用newInstance()方法即可。

1.2 要想创建对象成功,需要满足:
条件1:要求运行时类中必须提供一个空参的构造器
条件2:要求提供的空参的构造器的权限要足够。


1.3 回忆:JavaBean中要求给当前类提供一个公共的空参的构造器。有什么用?
> 场景1:子类对象在实例化时,子类的构造器的首行默认调用父类空参的构造器。
> 场景2:在反射中,经常用来创建运行时类的对象。那么我们要求各个运行时类都提供一个空参的构造器,便于我们编写通用的
       创建运行时类对象的代码。

1.4 在jdk9中标识为过时,替换成什么结构
通过Constructor类调用newInstance(...)

2. 反射应用2:获取运行时类的内部结构
2.1 (了解)获取运行时类的内部结构1:所有属性、所有方法、所有构造器
2.2 (熟悉)获取运行时类的内部结构2:父类、接口们、包、带泛型的父类、父类的泛型等


3. (掌握)反射的应用3:调用指定的结构:指定的属性、方法、构造器
3.1 调用指定的属性(步骤)
步骤1.通过Class实例调用getDeclaredField(String fieldName),获取运行时类指定名的属性
步骤2. setAccessible(true):确保此属性是可以访问的
步骤3. 通过Filed类的实例调用get(Object obj) (获取的操作)
                  或 set(Object obj,Object value) (设置的操作)进行操作。

3.2 调用指定的方法(步骤)
步骤1.通过Class的实例调用getDeclaredMethod(String methodName,Class ... args),获取指定的方法
步骤2. setAccessible(true):确保此方法是可访问的
步骤3.通过Method实例调用invoke(Object obj,Object ... objs),即为对Method对应的方法的调用。
     invoke()的返回值即为Method对应的方法的返回值
     特别的:如果Method对应的方法的返回值类型为void,则invoke()返回值为null

3.3 调用指定的构造器(步骤)
步骤1.通过Class的实例调用getDeclaredConstructor(Class ... args),获取指定参数类型的构造器
步骤2.setAccessible(true):确保此构造器是可以访问的
步骤3.通过Constructor实例调用newInstance(Object ... objs),返回一个运行时类的实例。



4. (了解)反射的应用4:通过反射获取注解的信息(见com.atguigu04.other.annotation包的测试)

复习:自定义注解
① 参照@SuppressWarnings 进行创建即可。
② 注解要想通过反射的方式获取,必须声明元注解:@Retention(RetentionPolicy.RUNTIME)

04-类中注解的调用

针对于注解中信息的获取

1. 公式: 框架 = 反射 + 注解 + 设计模式

2. (了解)自定义注解在框架中的使用

 

标签:反射,调用,class,机制,时类,Class,加载
From: https://www.cnblogs.com/callbin/p/17963862

相关文章

  • 安卓之内存管理,强制回收机制以及应对措施分析
    ​文章摘要        安卓操作系统作为全球最流行的移动操作系统之一,其强大的功能和灵活性深受开发者与用户的喜爱。然而,随着应用的复杂性和用户需求的增长,应用的内存管理变得尤为重要。在这其中,安卓的强制回收机制起着至关重要的作用。本文将深入探讨安卓系统中的内存管......
  • 面向对象之反射
    【一】反射【1】什么是反射反射是一种程序可以判断,取出和修改其本地状态或行为的能力在python中,反射主要是指通过字符串操作对象属性【2】Python中的反射同过字符串的形式操作对象相关的属性python一切皆为对象,都可以使用反射【二】反射方法【1】反射方法介绍getatt......
  • K8s核心技术-集群安全机制(概述),(RBAC实现鉴权)
    K8s核心技术-集群安全机制(概述)Kubernetes(K8s)是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。在Kubernetes集群中,安全是一个非常重要的考虑因素。集群安全机制旨在保护集群中的资源和敏感信息,防止未经授权的访问和恶意行为。集群安全机制包括以下方面:认证(Authe......
  • Python面向对象之反射
    【一】反射【1】什么是反射反射是一种程序可以访问、检测和修改其本身状态或行为的能力。在Python中,反射主要指通过字符串的形式操作对象的属性。【2】Python中的反射通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)【二】反射方法......
  • 基于k8s Deployment的弹性扩缩容及滚动发布机制详解
    k8s第一个重要设计思想:控制器模式。k8s里第一个控制器模式的完整实现:Deployment。它实现了k8s一大重要功能:Pod的“水平扩展/收缩”(horizontalscalingout/in)。该功能从PaaS时代开始就是一个平台级项目必备编排能力。若你更新了Deployment的Pod模板(如修改容器的镜像),则Deployment......
  • 22-安全机制:Kubernete 如何保障集群安全?
    (https://rancher.com/blog/2019/2019-01-17-101-more-kubernetes-security-best-practices/)你好,我是正范。Kubernetes作为一个分布式集群的管理工具,提供了非常强大的可扩展能力,可以帮助你管理容器,实现业务的高可用性和弹性能力,保障业务的规模。现在也有越来越多的企业正在逐步......
  • js 垃圾回收机制
    一、概述垃圾回收机制是为了防止内存的泄漏(已经不需要的某一块内存还一直存在着),垃圾回收机制就是不停歇的寻找这些不再使用的变量,并且释放掉他所指向的内存。2、变量的生命周期变量被声明、赋值(修改)、读取、不需要时释放,是变量的生命周期。js中的变量分为局部变量和全局变量。......
  • 详解GaussDB(DWS)通信安全的小妙招:连接认证机制
    本文分享自华为云社区《GaussDB(DWS)数据库安全系列之通信安全》,作者:yd_262982826。1.前言网络是一个开放的环境,仅仅依靠用户名和密码难以应对复杂的网络环境,针对可能存在的身份伪造的欺骗行为,以及监听通信内容的窃听行为,为了确保通信双方身份的真实性和通信内容的私密性,防止非法......
  • Python中的异常处理机制是什么
    在Python编程中,异常处理机制是一种重要的机制,用于捕获和处理程序中出现的异常情况。通过合理地使用异常处理,我们可以使程序更加健壮、稳定,并提供更好的用户体验。1.异常是什么?在编程中,异常是指在程序运行过程中发生的错误或异常情况。例如,除以零、索引越界、文件不存在等都属于异常......
  • Java反射遍历判断值是否属于枚举类Enum
    首先,是一个枚举类:publicenumAuditState{TO_BE_AUDIT(0,"待审核"),AUDITED(1,"已审核");privateStringmessage;privateIntegercode;AuditState(Integercode,Stringmessage){this.message......