我是 ABin-阿斌:写一生代码,创一世佳话。 如果小伙伴们觉得我的文章有点 feel ,那就点个赞再走哦。

一、具体介绍

反射机制的概述

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

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

1、理解Class类并获取Class实例

类的加载过程:

编译过程:
  当我们的程序经过 javac.exe 命令后,会生成一个或多个字节码文件(.class结尾)

运行过程:
  接着我们使用 java.exe 命令对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中,此过程就称为类的加载。加载到内存中的类,我们就称为运行时类,此运行时类,就作为 Class 的一个实例。
  说白了,Class 的实例所对应的就是一个运行时的类。

代码演示:

package com.mangobin.entity;public class Person {private String name;public  int age;//get/set/toString 略public Person(String name, int age) {this.name = name;this.age = age;}public Person(String name) {this.name = name;}public Person() {System.out.println("空参构造器获取了.....");}public void show(){System.out.println("2020年即将过去了。。。。");}private String showStart(String start){System.out.println("美好的2021年即将到来。。。。。" +start);return start;}
}
 /*** @Description: 获取Class的实例的方式(前三种方式需要掌握)*/@Testpublic void test03() throws ClassNotFoundException {//方式一:调用运行时类的属性:.classClass c1 = Person.class;System.out.println("调用运行时类的属性:" + c1);//方式二:通过运行时类的对象,调用getClass()Person person = new Person();Class c2 = person.getClass();System.out.println("通过运行时类的对象:" + c2);//方式三:调用Class的静态方法:forName(String classPath):实际开发当中用的最多Class c3 = Class.forName("com.mangobin.entity.Person");System.out.println("调用Class的静态方法:" + c3);//判断这三种获取方式的地址值是否相同,结果为:true,trueSystem.out.println(c1 == c2);System.out.println(c2 == c3);//方式四:使用类的加载器:ClassLoader  (实际开发当中用的比较少)ClassLoader classLoader = ReflectionTest.class.getClassLoader();Class c4 = classLoader.loadClass("com.mangobin.entity.Person");System.out.println("使用类的加载器:" + c4);System.out.println(c1 == c4);}

结果:

2、类的加载与ClassLoader的理解

类的加载过程:

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

类的加载器

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

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

类加载器的分类

Java类编译、运行的执行流程

代码演示

public class ClassLoaderTest {/*** @Description:  读取配置文件*/@Testpublic void test01() throws Exception {Properties properties = new Properties();//此时的文件默认在当前的module下。//读取配置文件的方式一://FileInputStream inputStream = new FileInputStream("jdbc.properties");
//        FileInputStream inputStream = new FileInputStream("src\\jdbc2.properties");
//        properties.load(inputStream);//读取配置文件的方式二:使用ClassLoader//配置文件默认识别为:当前module的src下ClassLoader loader = ClassLoaderTest.class.getClassLoader();InputStream is = loader.getResourceAsStream("jdbc2.properties");properties.load(is);String user = properties.getProperty("user");String password = properties.getProperty("password");System.out.println("用户名为:" + user + ", 密码为:" + password);}
}

结果:

二、具体操作

1、获取创建运行时类的对象

public class NewInstanceTest {@Testpublic void test01() throws Exception {Class<Person> c1 = Person.class;/*newInstance():调用此方法,创建对应的运行时类的对象。内部调用了运行时类的空参的构造器。要想此方法正常的创建运行时类的对象,要求:1.运行时类必须提供空参的构造器2.空参构造器的访问权限要允许。通常,设置为public。在javabean中要求提供一个public的空参构造器。原因:1.便于通过反射,创建运行时类的对象2.便于子类继承此运行时类时,默认调用super()时,保证父类有此构造器*/Person obj =  c1.newInstance();System.out.println("创建对象实例为:" + obj);}/*** 反射的动态获取*/@Testpublic void test02(){for(int i = 0;i < 20;i++) {int num = new Random().nextInt(3);String classPath = "";switch (num) {case 0:classPath = "java.util.Date";break;case 1:classPath = "java.lang.Object";break;case 2:classPath = "com.mangobin.entity.Person";break;}try {Object obj  = getInstance(classPath);System.out.println(obj);}catch (Exception e){e.printStackTrace();}}}/*** 创建一个指定类的对象。* classPath:指定类的全类名*/public Object getInstance(String classPath) throws Exception {Class c1 = Class.forName(classPath);System.out.println("指定类的全类名为:" + c1);return c1.newInstance();}
}

2、获取运行时类的完整结构

public class FieldTest {@Testpublic void test01(){Class c1 = Person.class;//获取属性结构//getFields():获取当前运行时类及其父类中声明为public访问权限的属性//这里的 Field[] 主要是为了存储多个属性,便于我们获取Field[] fields = c1.getFields();for (Field field : fields) {System.out.println("当前获取到的属性为:" +field);}System.out.println();//getDeclaredFields():获取当前运行时类中声明的所有属性。(不包含父类中声明的属性)Field[] f1 = c1.getDeclaredFields();for (Field field : f1) {System.out.println(field);}}/*** @Description:  获取权限修饰符、变量、数据类型*/@Testpublic void test02(){Class c1 = Person.class;//1.获取权限修饰符//getDeclaredFields():获取当前运行时类中声明的所有属性。(不包含父类中声明的属性)//这里的 Field[] 主要是为了存储多个属性,便于我们获取Field[] f = c1.getDeclaredFields();for (Field field : f) {int modifier = field.getModifiers();//System.out.print(modifier); // 2 0 1 :这里是根据源码 Modifier 这个中的一个常量来定义的System.out.print(Modifier.toString(modifier) + "\t");//2.获取数据类型Class type = field.getType();System.out.print(type.getName() + "\t");//3.获取变量名String name = field.getName();System.out.print(name);System.out.println();}}
}

3、调用运行时类的指定结构

@MyAnnotation(value="good")
public class Person extends Animal<String> implements Comparable<String>,MyInterface{private String name;int age;public int id;//get/set/toString 略public Person(String name, int age) {this.name = name;this.age = age;}@MyAnnotation(value="nice")public Person(String name) {this.name = name;}public Person() {System.out.println("空参构造器被获取了.....");}private static void show(){System.out.println("2020年即将过去了。。。。");}@MyAnnotationprivate String showStart(String start){System.out.println("接下来就是美好的事物了:" +start);return start;}@Overridepublic void info() {System.out.println("我是一只小熊熊~~~~~~~");}@Overridepublic int compareTo(String o) {return 0;}
}
public class ReflectionTest {@Testpublic void testField() throws Exception {Class c1 = Person.class;//创建运行时的类对象Person person = (Person) c1.newInstance();//1. getDeclaredField(String fieldName):获取运行时类中指定变量名的属性Field name = c1.getDeclaredField("name");//2.保证当前属性是可访问的name.setAccessible(true);//3.获取、设置指定对象的此属性值name.set(person,"测试");System.out.println(name.get(person));}/*** @Description: 如何操作运行时类中的指定的方法 -- 需要掌握*/@Testpublic void testMethod() throws Exception {Class c1 = Person.class;//创建运行时的类对象Person person = (Person) c1.newInstance();/*1.获取指定的某个方法getDeclaredMethod():参数1 :指明获取的方法的名称  参数2:指明获取的方法的形参列表*/Method showStart = c1.getDeclaredMethod("showStart", String.class);//2.保证当前方法是可访问的showStart.setAccessible(true);/*3. 调用方法的invoke():参数1:方法的调用者  参数2:给方法形参赋值的实参invoke()的返回值即为对应类中调用的方法的返回值。*/Object returnValue = showStart.invoke(person, "二零二一年元旦节即将到来~~~~");System.out.println(returnValue);System.out.println("**************如何调用静态方法****************");//获取 Person 类中的静态方法Method show = c1.getDeclaredMethod("show");//开启所有访问权限show.setAccessible(true);//如果调用的运行时类中的方法没有返回值,则此invoke()返回nullObject returnVal = show.invoke(Person.class);System.out.println(returnVal);}/*** @Description: 如何调用运行时类中的指定的构造器*/@Testpublic void testConstructor() throws Exception {Class c1 = Person.class;/*1.获取指定的构造器getDeclaredConstructor():参数:指明构造器的参数列表*/Constructor constructor = c1.getDeclaredConstructor(String.class);//2.保证此构造器是可访问的constructor.setAccessible(true);//3.调用此构造器创建运行时类的对象Person person = (Person) constructor.newInstance("魔都");System.out.println(person);}
}

Java基础:反射的详细介绍与使用相关推荐

  1. Java基础-Date类常用方法介绍

    Java基础-Date类常用方法介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.毫秒值概念 我们在查阅Date类的API文档时,会发现这样的一句话:"The cl ...

  2. java中char占的二进制,java数据类型与二进制详细介绍

    java数据类型与二进制详细介绍 在java中 Int 类型的变量占 4个字节 Long 类型的变量占8个字节 一个程序就是一个世界,变量是这个程序的基本单位. Java基本数据类型 1. 整数类型 ...

  3. java基础-Eclipse开发工具介绍

    java基础-Eclipse开发工具介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 所谓工欲善其事必先利其器,即将身为一名Java开发工程师怎么能没有一款好使的IDE呢?今天就 ...

  4. java基础-BigDecimal类常用方法介绍

    java基础-BigDecimal类常用方法介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.BigDecimal类概述 我们知道浮点数的计算结果是未知的.原因是计算机二进制 ...

  5. java基础-Idea开发工具介绍

    java基础-Idea开发工具介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 之前给大家介绍过一款Java的IDE叫eclipse,有些功能用起来不是很得心应手,尤其是在导报的 ...

  6. Java Scanner类的详细介绍(Java键盘输入)

    Java Scanner类的详细介绍(Java键盘输入) 一.Scanner类的简单使用 二.Scanner类的详细介绍 1.判断输入数据类型 2.next()与nextLine()的区别 3.求多个 ...

  7. 16、Java 基础-反射

    Java 反射 1.反射 反射是指程序可以访问.检测.修改它本身的状态或行为的一种能力. 2.Java的反射机制 java的反射机制是指在程序的运行状态中,给定任意一个类,都可以获取到这个累的属性和方 ...

  8. [Java基础] 反射机制汇总

    引言 初学Java反射机制的时候,只是感觉很神奇,但是不知道学了该怎么用,所以过了一段时间就忘得差不多了:最近接触到了框架,在学习中遇到了反射,深深体会到了反射机制的神奇,回来复习了一下反射机制,写一 ...

  9. java基础反射知识总结_非常好的Java基础反射总结

    前言疯狂复习基础ing- 最近复习的Jv基础反射做了应该总结,果然反射不只有那么一点点东西,多的是精髓! 最重要的是最后推荐的那两篇文章,写的非常非常好!!反射 1.反射的原理Jv反射机制就是在运行状 ...

  10. java.security Cipher 对象详细介绍

    cipher对象:此类为java.securtiy 为密码进行加密,解密的对象,根据java 1.6 doc javadoc 介绍: 此类为加密和解密提供密码功能.它构成了 Java Cryptogr ...

最新文章

  1. 《黑客与画家》读后感:你对技术一无所知(一些金句)
  2. 关于Nginx的server_name。
  3. 在Python列表中删除重复元素的几种方法,用起来真好用
  4. 如何将本地 Windows 电脑中的文件复制(上传)到远程的 Windows 服务器主机上
  5. 丘成桐演讲全文:几何与计算数学的关系
  6. mysql数据库enum部分乱码_要慎用mysql的enum字段的原因
  7. vs使用未初始化的内存怎么解决_C语言内存操作陷阱总结
  8. modbus tcp调试助手_集成20几个功能的电气调试软件大放送,永久免费、持续升级...
  9. 豆瓣电影小程序服务器,微信小程序实战:仿豆瓣电影
  10. Windows 10 下如何显示文件的后缀名
  11. 强力回击 跨境侵权(TRO)卖家通过诉讼大获全胜,还净赚数万?
  12. 论文阅读—图像分割方法综述(二)(arXiv:[cs:cv]20200410)
  13. 宝宝营养粥及如何提高宝宝睡眠
  14. 最长匹配括号子序列问题
  15. 毕业设计实用模型(四)——回归模型的实现(R语言)
  16. 汇川H5U模拟量输入模拟量转换 FC S_ITR
  17. Android手机通过USB数据线共享Linux电脑网络
  18. 51“motorrr”寻迹小车学习1电机和寻迹模块
  19. Shell和Jenkins讲解
  20. scratch小游戏--守护地球

热门文章

  1. python在tk界面播放本地视频_tkinter做一个本地视频播放器(2)——弹幕
  2. 指纹登录的计算机忘记密码怎么办,华为有指纹忘了锁屏密码怎么办
  3. Android倒计时定时器CountDownTimer的用法
  4. 掌握模拟电路设计需要阅读的几本参考书!
  5. 从原型图到成品:步步深入 CSS 布局
  6. Oracle-07:别名,去重,子查询
  7. Sentinel中有时候会搞乱的blockHandler与fallback
  8. 协议h2怎么php,net::ERR_SPDY_PROTOCOL_ERROR 错误 h2 协议,这个具体是什么引起的?
  9. Coarse-Grain Fine-Grain Coattention Network for Multi-Evidence Question Answering
  10. R中gRain包的加载和使用