当前位置: 首页 > news >正文

15. Java反射和注解

Java —— 反射和注解

      • 1. 反射
      • 2. 注解

1. 反射

动态语言:变量的类型和属性可以在运行时动态确定,而不需要在编译时指定
常见动态语言:Python,JavaScript,Ruby,PHP,Perl;常见静态语言(C,C++,C#,Go,Java)
Java:Java并不算是严格意义上的动态语言,从反射角度来说属于半动态语言(能通过反射机制实现了部分动态编程的能力)
Java反射机制:Java编程语言提供的一种强大的特性,它允许程序在运行时动态地获取类的信息,并通过该信息操作类的成员变量、方法和构造函数

Java 的反射机制:在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法;并且对于任意一个对象,都能够调用它的任意一个方法

Java反射常用API
Class 类:反射的核心类,可以获取类的属性,方法等信息
Field 类:Java.lang.reflec 包中的类,表示类的成员变量,可以用来获取和设置类之中的属性值
Method类: Java.lang.reflec 包中的类,表示类的方法,它可以用来获取类中的方法信息或者执行方法
Constructor 类: Java.lang.reflec 包中的类,表示类的构造方法
获取Class对象的3种方法
           调用某个对象的getClass()方法
             ❶ 类名 对象名 = new 类名();
             ❷ Class 类对象名 = 对象名.getClass();
           使用Class类中的forName()静态方法(安全且性能好)
             ❸ Class 类对象名 = Class.forName(“类的完全限定名”);
高版本Java创建:var 类对象名 = 类名(需要创建类对象的类).class;
        Class<类型(类名)> 类对象名 = 类名(需要创建类对象的类.class;

  • 对应类的常用方法
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
  • 对应代码
package reflect;import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;/*** 反射机制*/public class TestDemo {public static void main(String[] args) throws NoSuchMethodException,InvocationTargetException, IllegalAccessException,InstantiationException, NoSuchFieldException {// 创建类对象var classes = Information.class;System.out.println("类名:" + classes.getSimpleName());// 根据类获取当前类的完全限定名String className = classes.getName();System.out.println("当前类的完全限定名:" + className);// 根据获取当前类的包名String packageName = classes.getPackageName();System.out.println("包名:" + packageName);// 根据类获取当前普通方法名List<String> list = new ArrayList<>();Method[] methods = classes.getMethods();for (Method method : methods) {list.add(method.getName());}System.out.println("public方法个数:" + list.size());System.out.println("public方法:" + list);// 获取构造器(无参构造器)Constructor<Information> constructor = classes.getConstructor();// 利用无参构造器创建实例Object obj = constructor.newInstance();// 获取指定的普通方法,带参数Method publicMethod = classes.getMethod("publicMethod", String.class, int.class);// 获取指定私有方法Method privateMethod = classes.getDeclaredMethod("privateMethod", String.class);System.out.println("获取指定私有方法:" + privateMethod);// 强行开启私有方法访问权限privateMethod.setAccessible(true);// 获取所有普通public属性Field[] fields = classes.getFields();System.out.println("普通属性:" + Arrays.toString(fields));// 获取所有属性Field[] declaredFields = classes.getDeclaredFields();System.out.println("所有属性:" + Arrays.toString(declaredFields));// 获取属性名for (Field field:declaredFields) {String name = field.getName();System.out.print(name + ", ");}System.out.println();// 访问单个私有属性Field name = classes.getDeclaredField("name");// 强行打开权限name.setAccessible(true);System.out.println("访问单个私有属性:名称:" + name.getName() + "   类型:" +name.getType() + "  权限修饰符(二进制位标识的修饰符信息):" + name.getModifiers());// 私有方法调用privateMethod.invoke(obj, "零零");// 方法调用publicMethod.invoke(obj, "夏鸥", 22);System.out.println("无参构造器创建的实例:" + obj);// 获取有参构造器Constructor<Information> constructors = classes.getConstructor(String.class, int.class, String.class);// 有参构造器创建实例Object object = constructors.newInstance("王菲", 20, "2020002");// 获取指定的普通方法Method classesMethod = classes.getMethod("publicMethod");// 方法调用classesMethod.invoke(object);System.out.println("有参构造器创建的实例:" + object);}
}class Information{private String name = "赫敏";private int age = 20;public String num = "2020001";public Information() {}public Information(String name, int age, String num) {this.name = name;this.age = age;this.num = num;}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 String getNum() {return num;}public void setNum(String num) {this.num = num;}@Overridepublic String toString() {return "TestDemo{" +"name='" + name + '\'' +", age=" + age +", num='" + num + '\'' +'}';}private void privateMethod() {System.out.println(name + " 私有方法");}private void privateMethod(String name) {this.name = name;System.out.println(name + "  私有方法");}public void publicMethod() {System.out.println(name + " 普通方法");}public void publicMethod(String name, int age) {this.name = name;this.age = age;System.out.println(name + age + " 普通方法");}
}
  • 应用实例
package reflect;import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.URISyntaxException;
import java.net.URL;/*** 要求:实例化与当前类在统一和包中的所有类*/
public class Instantiations {public static void main(String[] args) throws ClassNotFoundException, URISyntaxException, NoSuchMethodException,InvocationTargetException, InstantiationException, IllegalAccessException {/* 1. 获取当前包中的所有类名 */// 获取包名String packageName = Instantiations.class.getPackageName();// 获取当前绝对路径资源  ".":表示当前路径URL path = Instantiations.class.getResource(".");// 获取路径下的所有文件File file = new File(path.toURI());// 将所需文件过滤存储到数组(所有类)File[] files = file.listFiles(f -> f.getName().endsWith(".class"));// 获取到for (File sub:files) {String name = sub.getName();// 获取类名String className = name.replace(".class", "");System.out.println("实例化类:" + packageName + "." + className);Class<?> classes = Class.forName(packageName + "." + className);// 通过无参构造器创建实例Object obj = classes.getConstructor().newInstance();System.out.println(obj);}}
}

2. 注解

注解:元数据 / 注解(注解Annotation是一个接口),一种提供程序中元素信息和数据的途径和方法
作用:在不改变程序主体逻辑的情况下,为程序员提供额外的元数据信息(标记一段代码的功能、作用范围、参数要求等信息)

4种标准元注解:元注解的作用是负责注解其他注解
       ❶ @Target 注解修饰范围 / 修饰的目标元素类型
       ❷ @Retention:注解生命周期 / 保留级别 / 被保留的时间长短
       ❸ @Documented注解是否会被包含在Java文档中生成
       ❹ @Inherited注解是否可以被继承
  @Target元素类型
       ElementType.TYPE:类、接口或枚举类型
       ElementType.FIELD:字段或属性
       ElementType.METHOD:方法
       ElementType.PARAMETER:方法参数
       ElementType.CONSTRUCTOR:构造函数
       ElementType.LOCAL_VARIABLE:局部变量
       ElementType.ANNOTATION_TYPE:注解类型
       ElementType.PACKAGE:包
  @Retention的三个值
       RetentionPolicy.SOURCE:注解仅存在于源代码中,编译时会被丢弃
       RetentionPolicy.CLASS:注解存在于源码和编译后的字节码文件中,但在运行时会被丢弃(默认值)
       RetentionPolicy.RUNTIME:注解在运行时保留在字节码文件中,可以通过反射机制读取
  @Documented和@Inherited
       一个注解被@Documented修饰,那么它的信息将会被包含在生成的文档中
       一个注解被@Inherited修饰,表示该注解可以被子类继承

  • 基本原则:不直接干扰程序代码的运行
    Java 注解是一种元数据,它可以提供对程序元素(如类、方法、字段等)的额外信息或配置,并且不会直接影响程序的运行逻辑,只是一种机制,用于存储和传递额外的信息
  • 注解分类
    在这里插入图片描述

  • 声明注解及变长参数

package reflect.annotations;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;// 注解类型
@Target(ElementType.METHOD)
// 注解级别
@Retention(RetentionPolicy.RUNTIME)
// 声明注解
public @interface AutoRunMethod {// 注解的参数(当注解下的参数只有一个时,一般用value)int value() default 1;String name() default "张三";
}
  • 使用注解
package reflect;import reflect.annotations.AutoRunClass;
import reflect.annotations.AutoRunMethod;import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.util.Arrays;public class Reflect {public static void main(String[] args) {// 加载包下被注解的类被注解的方法try {String packName = Reflect.class.getPackage().getName();File dir = new File(Reflect.class.getResource(".").toURI());File[] subs = dir.listFiles(f->f.getName().endsWith(".class"));for (File sub:subs) {String className = sub.getName().replace(".class","");Class classes = Class.forName(packName + "." + className);if (classes.isAnnotationPresent(AutoRunClass.class)){System.out.println("实例化:" + className);Constructor constructor = classes.getConstructor();Object obj = constructor.newInstance();System.out.println(obj);// 方法名获取Method[] methods = classes.getDeclaredMethods();for (Method method:methods) {// 判断该方法是否被注解if (method.isAnnotationPresent(AutoRunMethod.class)){System.out.println("调用方法:" + method.getName() + "()");// 获取注解参数AutoRunMethod arm = method.getAnnotation(AutoRunMethod.class);// 获取值(定义时将其认为参数,调用时看作方法)int value = arm.value();String name = arm.name();System.out.println("注解参数的值:" + value + name);// 根据注解参数的值调用方法for (int i = 0; i < value; i++) {// 方法调用method.invoke(obj);}}}}}} catch (URISyntaxException | ClassNotFoundException |NoSuchMethodException | InstantiationException |IllegalAccessException | InvocationTargetException e) {throw new RuntimeException(e);}}
}// 注解类
@AutoRunClass
class Student {public String address = "贵阳市花溪区";private String name = "赵涛";private char gender = '男';private int age = 15;public Student() {}public Student(String name, char gender, int age) {this.name = name;this.gender = gender;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public char getGender() {return gender;}public void setGender(char gender) {this.gender = gender;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}// 注解方法@AutoRunMethod(3)public void sayHi() {System.out.println(name + ":你好");}@AutoRunMethod(value = 2, name = "李四")public void sleep() {System.out.println(name + ":睡觉");}@AutoRunMethod(name = "王五")public void watchTV() {System.out.println(name + ":看电视");}public void playGame() {System.out.println(name + ":玩游戏");}public void say(String info) {System.out.println(name + "说:" + info);}public void say(String info, int count) {System.out.println(name + "说了" + count + "次," + info);}public void study() {System.out.println(name + "学习");}@AutoRunMethodpublic void doHomework() {System.out.println(name + ":做作业");}// **********************普通方法(参数变长)只是Java编译器认可(最终为数组)***************************// 变长参数只能在方的最后一个参数,且一个方法只能有一个变长参数public void doSome(String... s) {System.out.println("参数个数:" + s.length);System.out.println("参数:" + Arrays.toString(s));}private void privateMethod() {System.out.println("这是一个私有方法");}@Overridepublic String toString() {return "Student{" +"address='" + address + '\'' +", name='" + name + '\'' +", gender=" + gender +", age=" + age +'}';}
}
  • 变长参数只能在方的最后一个参数,且一个方法只能有一个变长参数
  • 注解格式:
          类型 参数名() [default 默认值] 注:不指定默认值时使用注解必须传递对应参数
  • 注解传参机制:
    当注解仅有一个参数,且参数名为value时,直接传入参数(不需要参数名)
    当注解仅有一个参数,且参数名不为value时,正常使用注解传参语法:参数名=参数值
    多个参数传参使用参数名进行传参,传参顺序可以与注解定义时参数顺序不一致
    有多个参数时,即使一个注解的参数名为value,在实际使用时参数名也不可以忽略

相关文章:

15. Java反射和注解

Java —— 反射和注解 1. 反射2. 注解 1. 反射 动态语言&#xff1a;变量的类型和属性可以在运行时动态确定&#xff0c;而不需要在编译时指定 常见动态语言&#xff1a;Python&#xff0c;JavaScript&#xff0c;Ruby&#xff0c;PHP&#xff0c;Perl&#xff1b;常见静态语言…...

pdf处理工具 Enfocus PitStop Pro 2022 中文 for mac

Enfocus PitStop Pro 2022是一款专业的PDF预检和编辑软件&#xff0c;旨在帮助用户提高生产效率、确保印刷品质量并减少错误。以下是该软件的一些特色功能&#xff1a; PDF预检。PitStop Pro可以自动检测和修复常见的PDF文件问题&#xff0c;如缺失字体、图像分辨率低、颜色空…...

微信小程序入门开发教程

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《微信小程序开发实战》。&#x1f3af;&#x1f3a…...

php函数

1. strstr() 返回a在b中的第一个位置 2.substr() 截取字符串 3.PHP字符串函数parse_str(将字符串解析成多个变量)-CSDN博客 4.explode() 字符串分割为数组 5.trim&#xff08;&#xff09; 1.去除字符串两边的 空白字符 2.去除指定字符 6.extract()函数从数组里…...

3.3 封装性

思维导图&#xff1a; 3.3.1 为什么要封装 ### 3.3.1 为什么要封装 **封装**&#xff0c;在Java的面向对象编程中&#xff0c;是一个核心的思想。它主要是为了保护对象的状态不被外部随意修改&#xff0c;确保数据的完整性和安全性。 #### **核心思想&#xff1a;** - 保护…...

Redis魔法:点燃分布式锁的奇妙实现

分布式锁是一种用于在分布式系统中控制对共享资源的访问的锁。它与传统的单机锁不同&#xff0c;因为它需要在多个节点之间协调以确保互斥访问。 本文将介绍什么是分布式锁&#xff0c;以及使用Redis实现分布式锁的几种方案。 一、前言 了解分布式锁之前&#xff0c;需要先了…...

iOS 项目避坑:多个分类中方法重复实现检测

#前言 在项目中,我们经常会使用分类 -> category。category在实际项目中一般有两个左右:1.给已有class增加方法,扩充起能力、2.将代码打散到多个文件中,避免因为一个类过于复杂而导致代码篇幅过长(应用于viewController中很好用) 但是 category 也有很多弊端~ **首…...

【003】EIS数据分析_#LIB

EIS数据分析 1. EIS测试及数据获取2. EIS数据分析2.1 EIS曲线划分 1. EIS测试及数据获取 点击查看往期介绍 2. EIS数据分析 2.1 EIS曲线划分 一般来说&#xff0c;实轴处的截获表示体电阻(Rb)&#xff0c;它反映了电解质&#xff0c;隔膜和电极的电导率。高频区的半圆对应于…...

Sprint framework Day07:注解结合 xml 配置

前言 Spring注解结合XML配置是指在Spring应用中&#xff0c;使用注解和XML配置的方式来进行Bean的定义、依赖注入和其他配置。这种方式可以充分利用Spring框架的注解和XML配置两种不同的配置方式的特点。 在Spring框架中&#xff0c;我们可以使用注解来定义Bean&#xff0c;如…...

LiveGBS流媒体平台GB/T28181功能-国标流媒体服务同时兼容内网收流外网收流多网段设备收流

LiveGBS流媒体平台GB/T28181功能-国标流媒体服务同时兼容内网收流外网收流多网段设备收流 1、背景2、设备接入播放2.1、查看通道2.2、直播播放 3、默认收流地址配置4、其它网络设备收流配置5、搭建GB28181视频直播平台 1、背景 服务器部署的时候&#xff0c;可能有多个网卡多个…...

js题解(四)

文章目录 批量改变对象的属性判断是否包含数字判断是否符合指定格式 批量改变对象的属性 给定一个构造函数 constructor&#xff0c;请完成 alterObjects 方法&#xff0c;将 constructor 的所有实例的 greeting 属性指向给定的 greeting 变量。 function alterObjects(const…...

如何进行大数运算和高精度计算?

大数运算和高精度计算是在计算机编程中常见的需求&#xff0c;尤其是当处理大整数、分数、复数、浮点数等需要更多位数的数据时。在C语言中&#xff0c;由于原生的数据类型有限&#xff0c;您需要使用自定义的数据结构和算法来执行大数运算和高精度计算。在本文中&#xff0c;我…...

身份证读卡器跟OCR有何区别?哪个好?

二代身份证读卡器&#xff08;以下简称读卡器&#xff09;和OCR&#xff08;光学字符识别&#xff09;是两种常见的身份证信息获取技术&#xff0c;它们在原理、功能和应用方面存在一些区别。下面将详细介绍二者的区别并探讨哪个更好。 1. 原理&#xff1a; - 读卡器&#xff…...

华为云云耀云服务器L实例评测 | 实例评测使用之硬件参数评测:华为云云耀云服务器下的 Linux 网络监控神器 bmon

华为云云耀云服务器L实例评测 &#xff5c; 实例评测使用之硬件参数评测&#xff1a;华为云云耀云服务器下的 Linux 网络监控神器 bmon 介绍华为云云耀云服务器 华为云云耀云服务器 &#xff08;目前已经全新升级为 华为云云耀云服务器L实例&#xff09; 华为云云耀云服务器是什…...

C++ 设计模式 —— 组合模式

C 设计模式 —— 组合模式 0. 引用连接 本文主要的思路和代码&#xff0c;来自于对以下连接的学习和实现&#xff1a; 组合模式 1. 引言 1.1 什么是组合模式&#xff1f; 组合模式的定义组合模式的作用 组合模式是一种行为型设计模式&#xff0c;它将对象组合成树形结构以…...

华为云Stack的学习(九)

十、华为云Stack灾备服务介绍 1.云硬盘备份VBS 云硬盘备份服务&#xff08;VBS&#xff0c;Volume Backup Service&#xff09;可为云硬盘&#xff08;EVS&#xff0c;Elastic Volume Service&#xff09;创建备份&#xff0c;利用备份数据恢复云硬盘&#xff0c;最大限度保障…...

Flink中jobmanager、taskmanager、slot、task、subtask、Parallelism的概念

场景 一个工厂有三个车间每个车间两条生产线 生产流程如下 原料->加工->过滤->分类->美化->包装->下线 JobManager&#xff1a;工厂 在上述场景中&#xff0c;工厂就是jobManager&#xff0c;负责协调、调度和监控整个生产过程 TaskManager&#xff1a;车间…...

OpenHarmony docker环境搭建

OpenHarmony docker环境搭建 要求一台安装ubuntu的虚拟机,vscode软件 安装docker 在 Ubuntu 上安装 Docker 非常直接。我们将会启用 Docker 软件源&#xff0c;导入 GPG key&#xff0c;并且安装软件包。 首先&#xff0c;更新软件包索引&#xff0c;并且安装必要的依赖软件…...

【计算机网络】网络编程接口 Socket API 解读(11)

Socket 是网络协议栈暴露给编程人员的 API&#xff0c;相比复杂的计算机网络协议&#xff0c;API 对关键操作和配置数据进行了抽象&#xff0c;简化了程序编程。 本文讲述的 socket 内容源自 Linux man。本文主要对各 API 进行详细介绍&#xff0c;从而更好的理解 socket 编程。…...

Qt工具开发,该不该跳槽?

Qt工具开发&#xff0c;该不该跳槽? 就这样吧&#xff0c;我怕你跳不动。 嵌入式UI&#xff0c;目前趋势是向着LVGL发展。QT已经在淘汰期了。很多项目还在用&#xff0c;但技术上已经落后。QT短期内不会全面淘汰&#xff0c;但退位让贤的大趋势已经很清楚了。 最近很多小伙伴…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成

厌倦手动写WordPress文章&#xff1f;AI自动生成&#xff0c;效率提升10倍&#xff01; 支持多语言、自动配图、定时发布&#xff0c;让内容创作更轻松&#xff01; AI内容生成 → 不想每天写文章&#xff1f;AI一键生成高质量内容&#xff01;多语言支持 → 跨境电商必备&am…...