【 java 反射下篇】java反射机制不难吧?来看看这篇

news2024/9/21 0:42:50

📋 个人简介

  • 💖 作者简介:大家好,我是阿牛,全栈领域优质创作者。😜
  • 📝 个人主页:馆主阿牛🔥
  • 🎉 支持我:点赞👍+收藏⭐️+留言📝
  • 📣 系列专栏:java 小白到高手的蜕变🍁
  • 💬格言:要成为光,因为有怕黑的人!🔥
    请添加图片描述

目录

    • 📋 个人简介
  • 前言
    • 通过反射创建对应的运行时类对象
    • 通过反射获取运行时类的内部结构(了解)
      • 提供结构丰富的People
      • 获取运行时类的属性结构
      • 获取运行时类的方法结构
      • 获取运行时类的构造器结构
      • 获取运行时类的父类以及父类的泛型
      • 获取运行时类的接口,包,注解等
    • 通过反射调用运行时类的内部结构(重要)
      • 调用运行时类中的指定构造器
      • 调用运行时类中的指定属性
      • 调用运行时类中的指定方法
  • 结语

前言

本篇我将总结如何使用反射调用类的内部结构!

通过反射创建对应的运行时类对象

public static void main(String[] args) throws Exception {
        Class<People> cl = People.class;
        // newInstance():调用此方法创建对应的运行时类对象
        // java9之后,这个方法过期了,应使用getConstructor().newInstance()
        // 也就是先调用空参构造器,然后newInstance()创建对象
        People obj = cl.getConstructor().newInstance();
        System.out.println(obj);
    }

在这里插入图片描述
要想此方法正常的创建运行时类的对象,要求:
1.运行时类必须提供空参的构造器
2.空参的构造器的访问权限得够。通常,设置为 public 。
在 javabean 中要求提供一个 public 的空参构造器。原因:
1.便于通过反射,创建运行时类的对象
2.便于子类继承此运行时类时,默认调用 super ()时,保证父类有此构造器

通过反射获取运行时类的内部结构(了解)

提供结构丰富的People

这里提供一个结构丰富的People类用于下面的测试!

package java反射;

import java.io.Serializable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;

// 父类
class Creature<T> implements Serializable{
    private char sex;
    public double weight;

    private void breath(){
        System.out.println("呼吸");
    }
    public void eat(){
        System.out.println("吃东西");
    }
}
// 接口
interface Myinterface{
    void info();
}

// 注解
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation{
    String value() default "hello";
}
// 子类
@MyAnnotation(value="hi")
public class People extends Creature<String> implements Comparable<String>,Myinterface {
    private String name;
    int age;
    public int id;

    public People(){

    }
    @MyAnnotation(value="aniu")
    private People(String name) {
        this.name = name;
    }

    People(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @MyAnnotation
    private void show(String nation){
        System.out.println("国籍:" + nation);
    }

    public String display(String interests){
        return interests;
    }

    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public int compareTo(String o) {
        return 0;
    }

    @Override
    public void info() {
        System.out.println("我是一个人!");
    }
}

这个结构中有继承,注解,接口,泛型,以及不同权限的属性和方法等,接下类我们通过反射来获取这些结构学习!

获取运行时类的属性结构

public static void main(String[] args) {
        Class cls = People.class;
        // 获取属性结构
        // getFields():获取当前运行时类及其父类中声明为public的访问权限的属性
        Field[] fields = cls.getFields();
        for (Field item:fields){
            System.out.println(item);
        }

        System.out.println("------------------------------------");
        // getDeclaredFields():获取当前运行时类中生申明的所有属性(不包含父类中的属性)
        Field[] declaredFields = cls.getDeclaredFields();
        for (Field item:declaredFields){
            System.out.println(item);
            // 属性的权限修饰符 数据类型 变量名 也可单独获取到
            // 1.权限修饰符
            int modifiers = item.getModifiers();
            System.out.print(Modifier.toString(modifiers) + "\t");
            // 2.数据类型
            Class type = item.getType();
            System.out.print(type.getName() + "\t");
            // 3.变量名
            String name = item.getName();
            System.out.print(name);

            System.out.println("\n");
        }
    }

在这里插入图片描述

获取运行时类的方法结构

public static void main(String[] args) {
        Class cls = People.class;
        // getMethods() 获取当前运行时类以及父类中声明为public的方法
        Method[] methods = cls.getMethods();
        for(Method m:methods){
            System.out.println(m);
        }
        System.out.println("--------------------------");
        // getDeclaredMethods() 获取当前运行时类声明的所有方法(不包含父类)
        Method[] declaredMethods = cls.getDeclaredMethods();
        for(Method m:declaredMethods){
            System.out.println(m);
            // 方法也可以获取方法申明的注解 权限修饰符 返回值类型 方法名 形参列表 抛出的异常
            // 这里我只写一下获取方法的注解
            Annotation[] annotations = m.getAnnotations();
            for(Annotation a : annotations){
                System.out.println(a);
            }
        }
    }

在这里插入图片描述

获取运行时类的构造器结构

和上面的一样
getConstructors()和getDeclaredConstructors();,我不再写案例!

获取运行时类的父类以及父类的泛型

package java反射;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * @Author:Aniu
 * @Date:2023/1/17 21:35
 * @description 获取运行时类的父类以及父类的泛型
 */
public class Demo4 {
    public static void main(String[] args) {
        Class<People> cls = People.class;
        // getSuperclass() 获取运行时类的父类
        Class<? super People> superclass = cls.getSuperclass();
        System.out.println(superclass);

        System.out.println("--------------");

        // getGenericSuperclass() 获取运行时类的带泛型的父类
        Type genericSuperclass = cls.getGenericSuperclass();
        System.out.println(genericSuperclass);

        System.out.println("--------------");
        
        // 获取运行时类的带泛型的父类的泛型
        ParameterizedType genericSuperclass1 = (ParameterizedType) genericSuperclass;
        Type[] actualTypeArguments = genericSuperclass1.getActualTypeArguments();
        System.out.println(actualTypeArguments[0].getTypeName());
    }
}

在这里插入图片描述

获取运行时类的接口,包,注解等

package java反射;

import java.lang.annotation.Annotation;

/**
 * @Author:Aniu
 * @Date:2023/1/17 21:43
 * @description 获取运行时类的接口,包,注解等
 */
public class Demo5 {
    public static void main(String[] args) {
        Class<People> cls = People.class;
        // getInterfaces() 获取运行时类实现的接口 ,获取父类实现的接口:cls.getSuperclass().getInterfaces();
        Class<?>[] interfaces = cls.getInterfaces();
        for(Class c : interfaces){
            System.out.println(c);
        }
        System.out.println("------------------");

        // getPackage() 获取运行时类所在的包
        Package aPackage = cls.getPackage();
        System.out.println(aPackage);

        System.out.println("------------------");

        // getAnnotations() 获取运行时类的注解
        Annotation[] annotations = cls.getAnnotations();
        for(Annotation a : annotations){
            System.out.println(a);
        }
    }
}

在这里插入图片描述

通过反射调用运行时类的内部结构(重要)

调用运行时类中的指定构造器

package java反射;

import java.lang.reflect.Constructor;

/**
 * @Author:Aniu
 * @Date:2023/1/19 17:00
 * @description 调用运行时类中的指定构造器
 */
public class Demo8 {
    public static void main(String[] args) throws Exception {
        Class<People> cls = People.class;
        // 1.获取指定构造器
        // getDeclaredConstructor 参数:构造器的参数列表
        Constructor<People> declaredConstructor = cls.getDeclaredConstructor(String.class);
        // 2.保证此构造其实可访问的
        declaredConstructor.setAccessible(true);
        // 3.调用此构造器创建对象
        People p = declaredConstructor.newInstance("aniu");
        System.out.println(p);
    }
}

在这里插入图片描述
jdk9之后我们用这种方式创建运行时类的对象!即调用空参构造器创建运行时类的对象!

调用运行时类中的指定属性

package java反射;

import java.lang.reflect.Field;

/**
 * @Author:Aniu
 * @Date:2023/1/19 16:15
 * @description 调用运行时类中的指定属性
 */
public class Demo6 {
    public static void main(String[] args) throws Exception {
        Class<People> cls = People.class;
        // 创建运行时类的对象
        People p = cls.getConstructor().newInstance();
        
        // 获取指定的属性 getField()要求运行时类的属性权限修饰符为public
        // 通常不用此方法
        Field id = cls.getField("id");
        // 设置当前属性的值
        // set(): 参数:1:指明设置那个对象的属性  参数2:将此属性值设置为多少
        id.set(p,10);
        // 获取当前属性的值
        // get(): 参数1:获取那个对象当前的属性值
        int pid = (int) id.get(p);
        System.out.println(pid);

        System.out.println("--------------");
        
        // 1.获取指定的属性 通常用getDeclaredField
        Field name = cls.getDeclaredField("name");
        // 2.保证当前属性是可访问的 (对于private和默认权限的属性,设置和获取之前都要加这个)
        name.setAccessible(true);
        // 3.设置指定对象的此属性值
        name.set(p,"aniu");
        // 4.获取指定对象的此属性值
        String s = (String) name.get(p);
        System.out.println(s);
    }
}

在这里插入图片描述

调用运行时类中的指定方法

package java反射;

import java.lang.reflect.Method;

/**
 * @Author:Aniu
 * @Date:2023/1/19 16:39
 * @description 调用运行时类中的指定方法
 */
public class Demo7 {
    public static void main(String[] args) throws Exception {
        Class<People> cls = People.class;
        // 创建运行时类的对像
        People p = cls.getConstructor().newInstance();

        // 1.获取指定的某个方法   getMethod只能获取public
        // getDeclaredMethod所有权限方法都可获取。参数一:指明获取的方法的名称 参数二:指明获取的方法的形参列表
        Method show = cls.getDeclaredMethod("show", String.class);
        // 2. 保证当前方法可访问
        show.setAccessible(true);
        // 3. 调用方法
        // invoke() 参数一:方法的调用者 方法二:给方法的参数
        // invoke() 方法的返回值即为调用的类中方法的返回值
        Object c = show.invoke(p, "China");
        System.out.println(c);
    }
}

在这里插入图片描述
那如何调用静态方法呢?我给People类加一个静态方法:

public static void print(){
       System.out.println("我是阿牛!");
   }
Method print = cls.getDeclaredMethod("print");
print.setAccessible(true);
print.invoke(People.class); // 静态方法可以用类名直接调用

结语

如果你觉得博主写的还不错的话,可以关注一下当前专栏,博主会更完这个系列的哦!也欢迎订阅博主的其他好的专栏。

🏰系列专栏
👉软磨 css
👉硬泡 javascript
👉flask框架快速入门

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/172411.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Element Plus 跟踪表格数据总数,包括查询、筛选等操作

前言 Element Plus的表格组件提供了筛选功能 前端项目中&#xff0c;如果表格使用的是后端分页&#xff0c;使用表格插件及分页器插件就可以了。这种情况下&#xff0c;前端的表格筛选被后端的分页条件查询取代了 另一种情况&#xff1a;不分页&#xff0c;直接查询所有数据…

Win7快速部署weblogic 12c

0x00 前言 需要一个漏洞中等数量的版本。 0x01 安装环境 版本操作系统Windows 7 64bitJDKjdk-8u101-windows-x64weblogic12.2.1.3 0x02 下载地址 JDK 下载地址 https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.html jdk 1.8版本&#xff0c;文…

华为机试题:HJ16 购物单(python)

文章目录知识点详解1、input()&#xff1a;获取控制台&#xff08;任意形式&#xff09;的输入。输出均为字符串类型。2、print() &#xff1a;打印输出。3、strip()&#xff1a;删除字符串&#xff08;开头 / 结尾&#xff09;指定字符&#xff08;默认空格&#xff09;或字符…

两小时上手ActiveMQ

一、消息中间件概述 1.1 消息中间件产生的背景 在客户端与服务器进行通讯时.客户端调用后&#xff0c;必须等待服务对象完成处理返回结果才能继续执行。 客户与服务器对象的生命周期紧密耦合,客户进程和服务对象进程都都必须正常运行;如果由于服务对象崩溃或者网络故障导致用…

ceres学习笔记(四)

前言&#xff1a; 学习了pose_graph_2d部分&#xff0c;因为先学习了3维的pose_graph_3d部分&#xff0c;所以这个就比较容易。简单来说就是se2和se3的区别。整个的运行逻辑和3维部分的pose_graph_3d部分是一样的&#xff0c;概括为&#xff1a; 1.设置好两个type&#xff0c…

7、CenOS6安装Nginx

Nginx的安装与启动 什么是Nginx Nginx 是一款高性能的 http 服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器。由俄罗斯的程序设计师伊戈尔西索夫&#xff08;Igor Sysoev&#xff09;所开发&#xff0c;官方测试 nginx 能够支支撑 5 万并发链接…

《早安隆回》的铁粉,深圳80后男子不计成本,收购袁树雄签名照

谁也没有想到&#xff0c;五十多岁并且离异多年的袁树雄&#xff0c;靠着一首《早安隆回》&#xff0c;一夜之间红遍大江南北。如今《早安隆回》这首歌曲&#xff0c;已经拥有了三百万流量&#xff0c;有人说袁树雄下辈子都吃喝不愁&#xff0c;他的前妻该后悔了。 《早安隆回》…

ue4c++日记4(控制pawn类的运动|创建游戏模式|)

目录 代码速查 调用数学公式 获取位置/设置位置 绑定玩家输入按键&#xff0c;UE4传值给函数进行处理 约束获得的值再输出 创建对象 对象绑定到xxx上 设定默认玩家 实例&#xff1a;sin函数实现往复运动 实例&#xff1a;删除c类 1.删掉cpp和.h文件 2.删编译好的文件B…

缓存Caffeine之W-TinyLFU淘汰测录

我们常见的缓存是基于内存的缓存&#xff0c;但是单机的内存是有限的&#xff0c;不能让缓存数据撑爆内存&#xff0c;所有需要缓存淘汰机制。https://mp.csdn.net/editor/html/115872837 中大概说明了LRU的缓存淘汰机制&#xff0c;以及基于LRU的著名实现guava cache。除了LRU…

Python学习笔记——类(面向对象)

Python中使用类&#xff08;class〕来实现面向对象编程。Python中的类, 具有面向对象编程的所有基本特征&#xff1a;允许多继承、派生类可以重写它父类的任何方法、方法可以调用父类中同名的方法, 对象可以包含任意数量和类型的数据成员。创建类Python中, 使用class语句来创建…

Python 第7章 文件与数据格式化 笔记1

编码&#xff1a;print(云.encode(utf8))print(b\xe4\xba\x91.decode(utf8))要注意代码的编码方式。7.1文件概述windows中一个文件的完标识&#xff1a;D:\Downloads\新建文本文档.txt依次是路径&#xff0c;文件名主干&#xff0c;拓展名。没有包含除了文本字符以外的其他数据…

【JavaEE初阶】第四节.多线程基础篇 Thread类的使用、线程的几个重要操作和状态

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 一、Thread类的常见构造方法 二、Thread 的几个常见属性 三、和线程相关的几个重要的操作 3.1 启动线程 - start() 3.2 中断线程 3.3 等待线程 - join() …

JDK 8新特性之基本发展史

目录 一&#xff1a;Java SE的发展历史 二&#xff1a;Open JDK来源 三&#xff1a;Open JDK 和 Oracle JDK的关系 四&#xff1a;Open JDK 官网介绍 小结 &#xff1a; 一&#xff1a;Java SE的发展历史 Sun公司在1991年成立了一个称为绿色计划( Green Project )的项目&a…

Ubuntu22.04 美化

一&#xff1a;安装软件 sudo apt install gnome-tweaks chrome-gnome-shell sudo apt install gtk2-engines-murrine gtk2-engines-pixbuf sudo apt install sassc optipng inkscape libcanberra-gtk-module libglib2.0-dev libxml2-utils 二&#xff1a;安装GNOME扩展插件…

Windows 卸载 Visual Studio Code、MinGW-w64、CMake

文章目录1.卸载 Visual Studio Code1.1 在控制面板中找到 Visual Studio Code 将其卸载1.2 删除之前安装过的插件1.3 删除用户信息和缓存信息2.卸载 MinGW-w642.1 删除之前解压出来的文件夹2.2 删除之前配置过的环境变量3.卸载 CMake3.1 删除之前解压出来的文件夹3.2 删除之前配…

无 Hadoop 环境部署 Kylin4

1相比于 Kylin 3.x&#xff0c;Kylin 4.0 实现了全新 spark 构建引擎和 parquet 存储&#xff0c;使 kylin 不依赖 hadoop 环境部署成为可能。无Hadoop环境也降低了运维成本&#xff0c;减少了系统资源占用。 以下操作基于centos7.6 单机版本 部署版本信息如下 JDK 1.8Hive …

【Javascript】面向对象编程,this,原型与原型链,类与实例,class,实现Map,stack,Queue ,Set

❤️ Author&#xff1a; 老九 ☕️ 个人博客&#xff1a;老九的CSDN博客 &#x1f64f; 个人名言&#xff1a;不可控之事 乐观面对 &#x1f60d; 系列专栏&#xff1a; 文章目录对象中的方法/thisthis使用bind函数原型原型链类与实例classclass语法补充Map实现Map实现stack实…

【国产GD32芯片解析中科微北斗+GPS模块经纬度数据详细教程-附完整代码工程】

国产GD32芯片解析中科微北斗GPS模块经纬度数据详细教程-附完整代码工程简介准备工作PC端需要用到的工具代码下载地址GD32F103C8T6最小系统板代码实现GD32串口引脚定义如下&#xff1a;串口的初始化串口0初始化代码&#xff1a;串口1初始化代码串口的输入串口0的输入代码如下&am…

非标准包 game.rgss3a 的打开方法 | 2023 年实测

写在前面&#xff1a;最近在玩 RPG 游戏&#xff0c;想拆一个 Game.rgss3a 包&#xff0c;在网上找了很久的拆包方法&#xff0c;感觉写的比较凌乱&#xff0c;我来给大家整理一下吧。不过我本人的技术能力也很差&#xff0c;不确定说的是不是对的&#xff0c;就当是给大家提供…

中国智造助推跨境电商企业迈向全球市场

现今&#xff0c;跨境电商行业发展的如火如荼&#xff0c;中国智造也在不断助推跨境电商企业迈向全球市场。业内人员在新常态下的思想也有了一些改变&#xff0c;现在的跨境电商都是“平台物流”&#xff0c;在物流环节&#xff0c;也需要我们的专业团队去进行整合&#xff0c;…