java反射机制

1..获取Class实例的方式

1 @Test
 2     public void test3() throws ClassNotFoundException {
 3         //方式一:调用运行时类的属性:.class
 4         Class clazz1 = Person.class;
 5         System.out.println(clazz1);
 6         //方式二:通过运行时类的对象,调用getClass()
 7         Person p1 = new Person();
 8         Class clazz2 = p1.getClass();
 9         System.out.println(clazz2);
10
11         //方式三:调用Class的静态方法:forName(String classPath)
12         Class clazz3 = Class.forName("com.atguigu.java.Person");
13 //        clazz3 = Class.forName("java.lang.String");
14         System.out.println(clazz3);
15
16         System.out.println(clazz1 == clazz2);
17         System.out.println(clazz1 == clazz3);
18
19         //方式四:使用类的加载器:ClassLoader  (了解)
20         ClassLoader classLoader = ReflectionTest.class.getClassLoader();
21         Class clazz4 = classLoader.loadClass("com.atguigu.java.Person");
22         System.out.println(clazz4);
23
24         System.out.println(clazz1 == clazz4);
25
26     }

2.Class类的常用方法

(1)forName():返回指定类名name的Class对象

(2)getName():以 String 的形式返回此 Class 对象所表示的实体(类、接口、数组类、基本类型或 void)名称。

(3)newInstance():调用缺省的构造函数,返回该Class对象的一个实例

(4)getClassLoader():返回该类的类加载器

(5)getSuperclass():返回此Class所表示的实体的超类的Class

(6)Constructor[] getConstructors():返回一个包含某些Constructor对象的数组

(7)Field[] getDeclaredFields():返回Field对象的一个数组

(8)Method getMethod(String name,Class … paramTypes):返回一个Method对象,此对象的形参类型为paramType

3.哪些类型可以有Class对象?

(1)class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类

(2)interface:接口

(3)[]:数组

(4)enum:枚举

(5)annotation:注解@interface

(6)primitive type:基本数据类型

(7)void

三.反射应用

1.创建运行时类的对象

创建类的对象:调用Class对象的newInstance()方法

要求:类必须有一个无参构造器,且类的构造器的访问权限需要足够
或者调用有参构造器:

通过Class类的getDeclaredConstructor(Class … parameterTypes)取得本类的指定形参类型的构造器

代码显示:

1 @Test
2     public void testField() throws Exception {
3         Class clazz = Person.class;
4
5         //创建运行时类的对象
6         Person p = (Person) clazz.newInstance();
1 //1.根据全类名获取对应的Class对象
2 String name = "atguigu.java.Person";
3 Class clazz = null;
4 clazz = Class.forName(name);
5 //2.调用指定参数结构的构造器,生成Constructor的实例
6 Constructor con = clazz.getConstructor(String.class,Integer.class);
7 //3.通过Constructor的实例创建对应类的对象,并初始化类属性
8 Person p2 = (Person) con.newInstance("Peter",20);
9 System.out.println(p2);

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

我们可以通过反射,获取对应的运行时类中所有的属性、方法、构造器、父类、接口、父类的泛型、包、注解、异常等。。。。

获取属性结构:

1 @Test
 2 public void test1(){
 3
 4     Class clazz = Person.class;
 5
 6     //获取属性结构
 7     //getFields():获取当前运行时类及其父类中声明为public访问权限的属性
 8     Field[] fields = clazz.getFields();
 9     for(Field f : fields){
10         System.out.println(f);
11     }
12     System.out.println();
13
14     //getDeclaredFields():获取当前运行时类中声明的所属性。(不包含父类中声明的属性
15     Field[] declaredFields = clazz.getDeclaredFields();
16     for(Field f : declaredFields){
17         System.out.println(f);
18     }
19 }

获取方法:

1 @Test
 2 public void test1(){
 3
 4     Class clazz = Person.class;
 5
 6     //getMethods():获取当前运行时类及其所父类中声明为public权限的方法
 7     Method[] methods = clazz.getMethods();
 8     for(Method m : methods){
 9         System.out.println(m);
10     }
11     System.out.println();
12     //getDeclaredMethods():获取当前运行时类中声明的所方法。(不包含父类中声明的方法
13     Method[] declaredMethods = clazz.getDeclaredMethods();
14     for(Method m : declaredMethods){
15         System.out.println(m);
16     }
17 }

获取构造器结构:

1 @Test
 2     public void test1(){
 3
 4         Class clazz = Person.class;
 5         //getConstructors():获取当前运行时类中声明为public的构造器
 6         Constructor[] constructors = clazz.getConstructors();
 7         for(Constructor c : constructors){
 8             System.out.println(c);
 9         }
10
11         System.out.println();
12         //getDeclaredConstructors():获取当前运行时类中声明的所的构造器
13         Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
14         for(Constructor c : declaredConstructors){
15             System.out.println(c);
16         }
17
18     }

3.获取运行时类的指定结构

调用指定方法:

通过反射,调用类中的方法,通过Method类完成。步骤:

1.通过Class类的getMethod(String name,Class…parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的参数类型。

2.之后使用Object invoke(Object obj, Object[] args)进行调用,并向方法中传递要设置的obj对象的参数信息。

java反射机制

Object invoke(Object obj, Object … args)方法说明:

  • Object 对应原方法的返回值,若原方法无返回值,此时返回null
  • 若原方法若为静态方法,此时形参Object obj可为null
  • 若原方法形参列表为空,则Object[] args为null
  • 若原方法声明为private,则需要在调用此invoke()方法前,显式调用方法对象的setAccessible(true)方法,将可访问private的方法。

代码显示:

调用指定的属性:

1 调用指定的属性:
 2 @Test
 3 public void testField1() throws Exception {
 4     Class clazz = Person.class;
 5
 6     //创建运行时类的对象
 7     Person p = (Person) clazz.newInstance();
 8
 9     //1. getDeclaredField(String fieldName):获取运行时类中指定变量名的属性
10     Field name = clazz.getDeclaredField("name");
11
12     //2.保证当前属性是可访问的
13     name.setAccessible(true);
14     //3.获取、设置指定对象的此属性值
15     name.set(p,"Tom");
16
17     System.out.println(name.get(p));
18 }

调用指定的方法:

1 @Test
 2     public void testMethod() throws Exception {
 3
 4         Class clazz = Person.class;
 5
 6         //创建运行时类的对象
 7         Person p = (Person) clazz.newInstance();
 8
 9         /*
10         1.获取指定的某个方法
11         getDeclaredMethod():参数1 :指明获取的方法的名称  参数2:指明获取的方法的形参列表
12          */
13         Method show = clazz.getDeclaredMethod("show", String.class);
14         //2.保证当前方法是可访问的
15         show.setAccessible(true);
16
17         /*
18         3. 调用方法的invoke():参数1:方法的调用者  参数2:给方法形参赋值的实参
19         invoke()的返回值即为对应类中调用的方法的返回值。
20          */
21         Object returnValue = show.invoke(p,"CHN"); //String nation = p.show("CHN");
22         System.out.println(returnValue);
23
24         System.out.println("*************如何调用静态方法*****************");
25
26         // private static void showDesc()
27
28         Method showDesc = clazz.getDeclaredMethod("showDesc");
29         showDesc.setAccessible(true);
30         //如果调用的运行时类中的方法没返回值,则此invoke()返回null
31 //        Object returnVal = showDesc.invoke(null);
32         Object returnVal = showDesc.invoke(Person.class);
33         System.out.println(returnVal);//null
34
35     }

调用指定构造器:

1 @Test
 2 public void testConstructor() throws Exception {
 3     Class clazz = Person.class;
 4
 5     //private Person(String name)
 6     /*
 7     1.获取指定的构造器
 8     getDeclaredConstructor():参数:指明构造器的参数列表
 9      */
10
11     Constructor constructor = clazz.getDeclaredConstructor(String.class);
12
13     //2.保证此构造器是可访问的
14     constructor.setAccessible(true);
15
16     //3.调用此构造器创建运行时类的对象
17     Person per = (Person) constructor.newInstance("Tom");
18     System.out.println(per);
19
20 }

关于setAccessible方法的使用:

  1. Method和Field、Constructor对象都有setAccessible()方法。
  2. setAccessible启动和禁用访问安全检查的开关。
  3. 参数值为true则指示反射的对象在使用时应该取消Java语言访问检查。提高反射的效率。如果代码中必须用反射,而该句代码需要频繁的被调用,那么请设置为true。使得原本无法访问的私有成员也可以访问
  4. 参数值为false则指示反射的对象应该实施Java语言访问检查。

Original: https://www.cnblogs.com/xiuercui/p/13432174.html
Author: 程序界第一佳丽
Title: java反射机制

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/577547/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Linux运行Jar包方式

    1 运行Jar包 第一种方式 java -jar xxx.jar 最基本的方式,程序运行的信息会一直输出在控制台,ctrl+c中断或者关闭窗口时,程序中断执行。 第二种方式 jav…

    Linux 2023年6月7日
    0105
  • MySQL环境变量配置方法

    MySQL配置方法 下载免安装版本的MySQL数据库,大家根据自己的开发环境下载对应版本的数据库,我在此举例的是Windows系统下的配置方法,下载地址如下: https://de…

    Linux 2023年6月7日
    0100
  • 部署前后端为独立的 Docker 节点

    在『服务器部署 Vue 和 Django 项目的全记录』一文中,介绍了在服务器中使用 Nginx 部署前后端项目的过程。然而,当 Web 应用流量增多时,需要考虑负载均衡、流量分发…

    Linux 2023年6月7日
    0116
  • Linux中CentOS 7的安装及Linux常用命令

    前言 什么是Linux Linux是一套免费使用和自由传播的操作系统。说到操作系统,大家比较熟知的应该就是Windows和MacOS操作系统,我们今天所学习的Linux也是一款操作…

    Linux 2023年6月6日
    0141
  • Redis 主从复制

    Redis主从复制的原理 当建立主从关系时,slave配置slaveof 当redis生成dump.rdb文件时,工作过程如下 redis主进程fork一个子进程 fork出来的子…

    Linux 2023年5月28日
    094
  • Base-64字符串无效,The input is not a valid Base-64 string as it contains a non-base 64 character

    base64规则: 字符串只可能包含A-Z,a-z,0-9,+,/,=字符 字符串长度是4的倍数 =只会出现在字符串最后,可能没有或者一个等号或者两个等号 首先,C# 做上传文件的…

    Linux 2023年6月7日
    0115
  • WEB自动化-08-Cypress 接口测试

    8 接口测试 在服务和服务、系统和系统之间进行通信时,常常会使用到接口。通过接口测试,可以在项目早期更快发现问题。接口有很多类型,而现阶段使用的接口是基于HTTP协议的接口。 8….

    Linux 2023年6月7日
    0118
  • RestFul风格

    概念:Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格 设计的软件可以更简洁,更有层次,更易于实现缓存等机制。 功能资源:互联网所有的…

    Linux 2023年6月14日
    092
  • 备用链接

    win10 stick note 地址 https://www.partitionwizard.com/partitionmanager/where-are-sticky-note…

    Linux 2023年6月7日
    089
  • OpenSSL测试-大数

    任务详情 在openEuler(推荐)或Ubuntu或Windows(不推荐)中完成下面任务 基于OpenSSL的大数库计算2的N次方,N为你学号的后四位(5’) 基于…

    Linux 2023年6月8日
    097
  • Linux、Windows下Redis的安装即Redis的基本使用详解

    前言 什么是Redis Redis是一个基于 内存的key-value结构数据库。Redis 是互联网技术领域使用最为广泛的存储中间件,它是「 Remote Dictionary …

    Linux 2023年6月6日
    0117
  • lab 1

    int father[2],son[2]; int son[2]; if (fork() == 0) { int n; char buf[1]; close(0); dup(fat…

    Linux 2023年6月7日
    073
  • 并查集详解 图解引入到实现| Disjoint Sets details, intro to implementation with figures.

    Introduction of Disjoint Sets It’s easy to tell whether someone you know is your rel…

    Linux 2023年6月13日
    0113
  • Linux网络服务之部署YUM仓库

    镜像下载、域名解析、时间同步请点击阿里云开源镜像站 1 YUM简介 1.1 YUM简介 CentOS使用yum和dnf 解决rpm的包依赖关系。 YUM:rpm的前端程序,可解决软…

    Linux 2023年5月27日
    0121
  • mycat数据库集群系列之mycat读写分离安装配置

    最近在梳理数据库集群的相关操作,现在花点时间整理一下关于mysql数据库集群的操作总结,恰好你又在看这一块,供一份参考。本次系列终结大概包括以下内容:多数据库安装、mycat部署安…

    Linux 2023年6月14日
    0129
  • Docker搭建Redis Cluster集群及扩容和收容

    上一篇文章讲解了Redis集群原理及搭建,由于工作中使用docker较多,本文主要讲解使用docker搭建集群及对集群的扩展收容。环境:Centos7.6Docker:20.10….

    Linux 2023年6月13日
    078
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球