前言

在使用框架进行开发时,我们的开发速度大大提升。我们感叹于它的神奇之处,我们使用它的时候,也要知道其“灵魂”。正所谓,无反射,不框架,框架的灵魂就是反射。

另外,我们在eclipse或者IDEA中编辑Java代码时,它们是怎么知道我们的对象有哪些方法,输入一个点就能给提示呢?

带着问题我们来谈谈反射。

概念

反射:是将一个类的各个部分封装为其他对象,这就是反射机制。

看着上面文邹邹的话语,想必大家并没有理解啥是反射。下面我们来通过一个例子来进行讲解。

我们来看一下我们的Java代码在计算机中经历的几个阶段:

第一个阶段:源代码阶段

首先,我们定义一个猫的类,包含名字,年龄,无参和全参构造方法,和一个猫叫的方法。

Cat.java如下:

public class Cat {
private String name;//猫的名字
private int age;//猫的年龄 public Cat() {//无参构造方法
} public Cat(String name, int age) {//全参构造方法
this.name = name;
this.age = age;
} public void meow(){//猫叫的方法
System.out.println("喵喵喵~~~");
}
}

写完这个代码之后,我们并不能运行它,我们需要执行一个操作:编译。

通过Java自带的编译器,使用 javac 这个命令,编译 Cat.java 文件,如果编写的代码没有问题,会在磁盘上生成一个字节码文件:Cat.class 文件。

这个字节码文件放的是什么呢?

它主要包含三个主要的内容:

当然不止这三个内容,还有类的名称等等等等。

这就是java代码在计算机中的第一个阶段:

这时我们的代码还在硬盘,并没有进入内存。

我们先不谈第二个阶段,我们先来谈谈第三个阶段,也就是我们通常new对象的阶段。

第三个阶段:运行时阶段

这就是我们的运行时阶段。

从字节码文件到new出类的对象这又是一个怎样的过程呢?我们需要把字节码文件加载到内存中才能使用,这就要介绍我们的第二个阶段了。

第二个阶段:Class类对象阶段

在Java中万物皆对象,有一个对象来描述字节码文件;这个对象是Class类对象;

需要把字节码中的成员变量,构造方法,成员方法都表示出来,又这些可能不止一个,所以这三种需要由一个数组来存储,所以主要由三个主要的部分组成:

Field[] fields;//成员变量数组
Constuctor[] constuctors;//构造方法数组
Method[] method;//成员方法数组

可以看到,我们把它们存储到对象中了,然后就能够知道有哪些成员变量,哪些方法了,这就解答了我们前面的如何提示问题。

然后通过类对象创建对应的Cat类等对象。

三个阶段

获取字节码Class对象的三种方式

第一种方式

如果我们的java代码在第一个阶段时,它还没有进入内存,我们需要将它加载到内存,需要使用

Class.forName("全类名");方式将其加载到内存,获取Class对象;

第二种方式

如果我们的java代码在第二个阶段时,它还没有创建对象,但是我们已经把它它加载到了内存,获取到了它的类名,我们可以使用 类名.class的方式获取Class对象;

第三种方式

如果我们的java代码在第三个阶段时,已经有了该类的对象,我们只需要用 对象.getClass() 的方式获取Class对象;

下面我们就来演示一下这三种方法的使用;

首先我们创建一个包com.demo.domain(命名随自己来定),存放我们的实体类对象,本文使用Cat.java进行演示;

package com.demo.domain;

public class Cat {
private String name;//猫的名字
private int age;//猫的年龄 public Cat() {//无参构造方法
} public Cat(String name, int age) {//全参构造方法
this.name = name;
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public void meow(){//猫叫的方法
System.out.println("喵喵喵~~~");
}
}

再创建一个包com.demo.reflect用来演示这三种方式;Demo1.java如下:

package com.demo.reflect;

import com.demo.domain.Cat;

public class Demo1 {
public static void main(String[] args) throws ClassNotFoundException {
//第一种方式,Class.forName("全类名")
Class cls1 = Class.forName("com.demo.domain.Cat");
System.out.println(cls1);
//输出class com.demo.domain.Cat //第一种方式,类名.class
Class cls2 = Cat.class;//在使用Cat类之前需要进行导入
System.out.println(cls2);
//输出class com.demo.domain.Cat //第三种方式,已经具有对象,使用对象.getClass
Cat cat = new Cat();
Class cls3 = cat.getClass();
System.out.println(cls3);
//输出class com.demo.domain.Cat
}
}

注意:本文没写Class的泛型。

那获取到的三个对象是什么关系呢?我们用一段代码,验证它们的内存地址是否相等。

//比较三个对象
System.out.println(cls1 == cls2);//true
System.out.println(cls2 == cls3);//true

输出均为true,可见它们的内存地址是相同的。

所以,同一个字节码文件,在同一个程序运行的过程中,只会被加载一次,三种方式获取的Class对象都是同一个。

Class对象功能:

  • Class对象功能:

    • 获取功能:

      1. 获取成员变量们

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

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

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

        • Field getDeclaredField(String name)

      2. 获取构造方法们

        • Constructor<?>[] getConstructors()

        • Constructor getConstructor(类<?>... parameterTypes)

        • Constructor getDeclaredConstructor(类<?>... parameterTypes)

        • Constructor<?>[] getDeclaredConstructors()

      3. 获取成员方法们:

        • Method[] getMethods()

        • Method getMethod(String name, 类<?>... parameterTypes)

        • Method[] getDeclaredMethods()

        • Method getDeclaredMethod(String name, 类<?>... parameterTypes)

      4. 获取全类名

        • String getName()
  • Field:成员变量

    • 操作:

      1. 设置值

        • void set(Object obj, Object value)
      2. 获取值

        • get(Object obj)
      3. 忽略访问权限修饰符的安全检查

        • setAccessible(true):暴力反射
  • Constructor:构造方法

    • 创建对象:

      • T newInstance(Object... initargs)

      • 如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法

  • Method:方法对象

    • 执行方法:

      • Object invoke(Object obj, Object... args)
    • 获取方法名称:

      • String getName:获取方法名

反射好处

反射有很多的优势:

  1. 我们可以在程序运行过程中,操作这些对象。
  2. 可以为我们的程序进行解耦,提高程序的可扩展性。

相信大家对反射有了一定的了解,感谢大家的阅读。

欢迎关注

扫下方二维码即可关注微信公众号:code随笔

谈谈Java中的反射机制的更多相关文章

  1. java中的反射机制在Android开发中的用处

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

  2. 浅说Java中的反射机制(二)

    写过一篇Java中的反射机制,不算是写,应该是抄了,因为那是别人写的,这一篇也是别人写的,摘抄如下: 引自于Java基础--反射机制的知识点梳理,作者醉眼识朦胧.(()为我手记) 什么是反射? 正常编 ...

  3. 浅说Java中的反射机制(一)

    在学习传智播客李勇老师的JDBC系列时,会出现反射的概念,由于又是第一次见,不免感到陌生.所以再次在博客园找到一篇文章,先记录如下: 引用自java中的反射机制,作者bingoideas.(()为我手 ...

  4. 【Java基础】java中的反射机制与动态代理

    一.java中的反射机制 java反射的官方定义:在运行状态下,可以获取任意一个类的所有属性和方法,并且可通过某类任意一对象实例调用该类的所有方法.这种动态获取类的信息及动态调用类中方法的功能称为ja ...

  5. java 中利用反射机制获取和设置实体类的属性值

    摘要: 在java编程中,我们经常不知道传入自己方法中的实体类中到底有哪些方法,或者,我们需要根据用户传入的不同的属性来给对象设置不同的属性值,那么,java自带的反射机制可以很方便的达到这种目的,同 ...

  6. Java 中的反射机制

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

  7. 深入理解Java中的反射机制

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

  8. Java中的反射机制和动态代理

    一.反射概述 反射机制指的是Java在运行时候有一种自观的能力,能够了解自身的情况为下一步做准备,其想表达的意思就是:在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法:对于任意一个对象 ...

  9. Java中的反射机制Reflection

    目录 什么是反射? 获取.class字节码文件对象 获取该.class字节码文件对象的详细信息 通过反射机制执行函数 反射链 反射机制是java的一个非常重要的机制,一些著名的应用框架都使用了此机制, ...

  10. Java中的反射机制

    Java反射机制 反射机制定义 反射机制是Java语言中一个非常重要的特性,它允许程序在运行时进行自我检查,同时也允许其对内部成员进行操作.由于反射机制能够实现在运行时对类进行装载,因此能够增加程序的 ...

随机推荐

  1. 火山引擎 DataTester 应用故事:一个 A/B 测试,将产品 DAU 提升了数十万

      更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 疫情让线下的需求大量转移到线上,催生出了远程办公.网络授课.线上健身等新的生态现象.如何更好地为用户服务,提升 ...

  2. Linux 创建新用户

    添加用户组[root@VipSoft ~]#groupadd admin 添加用户[root@VipSoft ~]#useradd jimmy -m -d /home/jimmy -g admin 修 ...

  3. 【题解】Qin Shi Huang's National Road System HDU - 4081 ⭐⭐⭐⭐ 【次小生成树】

    During the Warring States Period of ancient China(476 BC to 221 BC), there were seven kingdoms in Ch ...

  4. 图解 Promise 实现原理(四)—— Promise 静态方法实现

    本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/Lp_5BXdpm7G29Z7zT_S-bQ作者:Morrain 了用法,原生提供了Promis ...

  5. SCA技术进阶系列(三):浅谈二进制SCA在数字供应链安全体系中的应用

    数字经济时代,随着开源应用软件开发方式的使用度越来越高,开源组件逐渐成为软件开发的核心基础设施,但同时也带来了一些风险和安全隐患.为了解决这些问题,二进制软件成分分析技术成为了一种有效的手段之一.通过 ...

  6. NET Core实战项目之CMS 设计篇 思维导图

    NET Core实战项目之CMS 第七章 设计篇-用户权限极简设计全过程 .NET Core实战项目之CMS 第八章 设计篇-内容管理极简设计全过程 .NET Core实战项目之CMS 第九章 设计篇 ...

  7. poj 2533 LIS(最长上升序列)

    ***一道裸题, 思路:在g数组内往里加元素,一直扩大这个数组,每次查询的时候,用二分查找,时间复杂度O(nlog(n)) *** #include<iostream> #include& ...

  8. 打 multi-fidelity RL 旗号,但是幼稚监督学习 + 迁移学习

    文章名称:Multi-fidelity reinforcement learning framework for shape optimization 链接:https://www.sciencedi ...

  9. 基于java+springboot的酒店预定网站、酒店客房管理系统

    该系统是基于Java的酒店客房预订系统设计与实现.是给师弟开发的毕业设计.现将源代码开放出来,感兴趣的同学可以下载. 演示地址 前台地址: http://hotel.gitapp.cn 后台地址: h ...

  10. 基于python+django的求职招聘网站-网上招聘管理系统设计与实现

    该系统是基于python+django的求职招聘网站.网上招聘管理系统.网上人才招聘系统.毕业生求职招聘系统.大学生求职招聘系统.校园招聘系统.企业招聘系统.系统适合场景:大学生.课程作业.毕业设计. ...