注解与反射基础

注解

概述

注解(Annotation),从jdk5.0引入。

作用

  • 不是程序本身,可以对程序作出解释(这一点和注释没什么区别)
  • 可以被其他程序读取

格式

注释是以“@注释名”在代码中存在的,还可以添加一些参数值。eg:

@SuppressWamings(value="unchecked")

使用位置

可以附加在package、class、method、field等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问。

内置注解

@Override:定义在java.lang.Override中,此注解只适用于修辞方法,表示一个方法声明打算重写超类中的另一个方法声明

@Deprecated:定义在java.lang.Deprecated中,此注释可以用于修辞方法、属性、类,表示不鼓励程序员使用这样的元素,通常是因为它很危险或者存在更好的选择。

不推荐使用,但是能够使用。

@SuppressWarnings:定义在java.lang.SuppressWarnings中,用来抑制编码时的警告信息,该注释需要添加一个参数才能正确使用,这些参数是已经定义好了的。

@SuppressWarnings("all")

@SuppressWarnings("unchecked")

@SuppressWarnings(value={"unchecked","deprecation"})

 

自定义注解,元注解

元注解

元注解的作用就是负责注解其他注解,Java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型作说明。这些类型和它们所支持的类在java.lang.annotation包中可以找到。(@Target、@Retention、@Documented、@Inherited)

  • @Target:用于描述注解的使用范围(被描述的注解可以用在什么地方)(方法、属性、类)
  • @Retention:表示需要在说明级别保存该注释信息,用于描述注解的生命周期
    • (SOURCE<CLASS<RUNTIME)分别代表源码、class、运行时
  • @Document:说明该注解将被包含在javadoc中
  • @Inherited:说明子类可以继承父类中得到该注解

自定义注解

使用@interface自定义注解,自动继承了java.lang.annotation.Annotation接口

  • @interface用来声明一个注解,格式:

public @interface注解名{定义内容}

  • 其中的每一个方法实际上是声明了一个配置参数。
  • 方法的名称就是参数的名称
  • 返回值类型就是参数的类型(返回值只能是基本类型,Class、String、enum)
  • 可以通过default来声明参数的默认值
  • 如果只有一个参数成员,一般参数名为value
  • 注解元素必须要有值,我们定义注解元素时,经常使用空字符串,0为默认值

以下自定义两个注解,作用域都是类和方法,在运行时生效。自定义两个方法,分别使用自定义的两个注解。 

反射机制

动态语言与静态语言

动态语言:是一类在运行时可以改变其结构的语言,例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化(在运行时代码可以根据某些条件改变自身的结构)。主要代码有:Object-C、C#、JavaScript、PHP、Python。

静态语言:运行时结构不可变的语言就是静态语言。eg:Java、C、C++。Java不是动态语言,但Java可以称为“准动态语言”,Java有一定的动态性,利用反射机制获得类似动态语言的特性

Java反射机制

Reflection(反射)是java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部消息,并能够直接操作任意对象的内部属性及方法

Class c=Class.forName("java.lang.String")

加载完类后,在堆内存的方法区中产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们通过这个对象看到类的结构,所有叫:反射

反射机制提供的功能:

  • 在运行是判断任意一个对象所属的类
  • 在运行是构造任意一个类所属的对象
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 在运行时获取泛型信息
  • 在运行时调用任意一个对象的成员变量和方法
  • 在运行时处理注解
  • 生成动态代理

反射优点:可以实现动态创建对象和编译,体现出很大的灵活性。

缺点:对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于直接执行相同的操作

主要API:

  • java.lang.Class:代表一个类
  • java.lang.reflect.Method:代表类的方法
  • java.lang.reflect.Field:代表类的成员变量
  • java.lang.reflect.Constructor:代表类的构造器

 定义一个实体类:

获取User类的class对象:

forName方法:返回具有给定字符串名称的类或接口关联的Class对象(返回指定名称的类的Class对象)

hashCode方法:每当在 Java 应用程序的执行期间对同一个对象多次调用时,hashCode 方法必须始终返回相同的整数,不同的对象返回不同的整数

Class类与获取Class实例

在Object类中定义了以下的方法,此方法将被所有子类继承

public final Class getClass()

以上的方法返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称

Class类的常用方法

static Class forName(String name)

返回指定类名name的class对象
Object newInstance()调用缺省构造函数,返回Class对象的一个实例
getName()返回此Class对象所表示的实体(类,接口,数组类或void)的名称
Class getSuperClass()返回当前Class对象的父类的Class对象
Class[] getinterfaces()获取当前Class对象的接口
ClassLoader getClassLoader()返回该类的类加载器
Constructor[] getConstructors()返回一个包含某些Constructor对象的数组
Method getMothed(String name,Class..T)返回Method对象,此对象的形参类型为paramType
Field[] getDeclaredFields()返回Field对象的一个数组

获取Class类的实例

  • 法一:若已知具体的类,通过类的Class属性获得,该方法最安全可靠,程序性能最高。

Class clazz=Person.class;//已知Person类

  • 法二:已知某个类的实例,调用该实例的getClass()方法获取Class对象。

Class clazz=person.getClass();//已知person对象

  • 法三:已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException。

Class clazz=Class.forName("demo01.Student");//已知demo01文件下的Student类

  • 内置级别数据类型可以直接用类名.Type
  • 可以利用Class Loader

 定义Person类,学生类,教师类

演示获取Class 实例的方法

 有Class对象的类型

  • class:外部类,成员(成员内部类、静态内部类),局部内部类、匿名内部类
  • interface:接口
  • enum:枚举
  • [ ]:数组
  • annotation:注解@interface
  • primitive type:基本数据类型
  • void

类的加载与ClassLoader

Java内存分为

    • 存放new的对象和数组
    • 可以被所有线程共享,不会存放别的对象引用
    • 存放基本变量类型(会包含这个基本类型的具体数值)
    • 引用对象的变量(会存放这个引用在堆里面的具体地址)
  • 方法区(特殊的堆)
    • 可以被所有的线程共享
    • 包含了所有的class和static变量

类的加载过程

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

详细解释:

  • 加载:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的Java.lang.Class对象
  • 链接:将Java类的二进制代码合并到JVM的运行状态之中的过程。
    • 验证:确保加载的类信息符合JVM规范,没有安全方面的问题
    • 准备:正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配。
    • 解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程。
  • 初始化
    • 执行类构造器<clinit>()方法的过程,类构造器<clinit>()方法是由编译器自动收集类中所有类变量的代码中的语句合并产生的。(类构造器时构造类信息的,不是构造该类对象的构造器)。
    • 当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化。
    • 虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确加锁和同步。

 内存:

发生类初始化的情况

类的主动引用(一定会发生类的初始化

  • 当虚拟机启动,先初始化main方法所在的类
  • new一个类的对象
  • 调用类的静态成员(除了final常量)和静态方法
  • 使用Java.lang.reflect包的方法对类进行反射调用
  • 当初始化一个类,如果其父类没有被初始化,则先回会初始化它的父类

 类的被动引用(不会发生类的初始化

  • 当访问一个静态域时,只有真正声明这个域的类才会被初始化,eg:当通过子类引用父类的静态变量,不会导致子类初始化
  • 通过数组定义类引用,不会触发此类的初始化
  • 引用常量不会触发此类的初始化(常量在链接阶段就存入调用类的常量池中了)                                   

设置一个父类Father,一个子类Son

eg:以下会发生类的初始化 

 eg:以下不会发生类的初始化

 

 

类加载器的作用 

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

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

类的加载器类型:

  • 引导类加载器:用C++编写的,是JVM自带的类加载器,负责Java平台核心库,用来装载核心类库,该加载器无法直接获取。
  • 扩展类加载器:负责jre/lib/ext目录下的jar包或-D java.ext.dirs指定目录下的jar包装入工作库
  • 系统类加载器:负责java-classpath或-D java..class.path所指的目录下的类与jar包装入工作库,是最常见的加载器

获取运行时类的完整结构

通过反射获取运行时类的完整结构:

Field、Method、Constructor、Superclass、Interface、Annotation

实现全部的接口、所继承的父类、全部的构造器、全部的方法、全部的Field、注解

具体用法:前提:创建User类

User中属性有:Phone、name、id、age,具体方法属性如下:

获取类结构具有以下方法:

  • getName:获得包名+类名
  • getSimpleName:获得类名
  • getFields:获得public属性
  • getDeclaredFields:获得所有属性
  • getDeclaredField:获得指定属性的值

  • getMethods: 获得本类及其父类的全部public方法
  • getDeclaredMethods:获得本类的所有方法
  • getMethod:方法名一样时,给出参数

 getConstructors:获得public构造器

getDeclaredConstructors:获得本类构造器

getDeclaredConstructor:获得指定的构造器

 创建运行时类的对象 

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

  • 类必须有一个无参数的构造器
  • 类的构造器的访问权限需要足够

没有无参的构造器创建对象:在操作的时候明确的调用类中的构造器,并将参数传递进去,才可以实例化操作

步骤如下:

  1. 通过Class类的getDeclaredConstructor(Class....parameterTypes)取得本类的指定形参类型的构造器
  2. 向构造器的形参中传递一个对象数组进去,里面包含了构造器中所需的各个参数。
  3. 通过Constructor实例化对象

扩展

invoke:激活

方法.invoke(对象,“方法的值”) 

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

 Method和Field、Constructor对象都有setAccessible()方法

setAccessible作用是启动和禁用访问安全检查的开关

  1. 参数值为true则指示反射的对象在使用时应该取消Java语言访问检查。
    • 提高反射的效率,如果代码中必须用反射,而该句代码需要频繁的被调用,那么请设置为true。 
    • 使得原本无法访问的私有成员也可以访问
  2. 参数值为flase则指示反射的对象应该实施Java语言访问检查

 反射操作注解

ORM:Object relationship Mapping-->对象关系映射

eg:

class Student{

        int id;

        String name;

        int age;

}

以上代码对应:

idnameage
001张三17
002李四16
  • 类和表结构对应
  • 属性和字段对应
  • 对象和记录对应

利用注解和反射完成类和表结构的映射关系

创建学生类Student2

创建注释:

 

在学生类中使用注解

 使用:

getAnnotation:返回注解信息

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

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

相关文章

SliverAppBar的功能和用法

文章目录 1 概念介绍2 使用方法3 示例代码 我们在上一章回中介绍了SliverGrid组件相关的内容&#xff0c;本章回中将介绍SliverAppBar组件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1 概念介绍 我们在本章回中介绍的SliverAppBar和普通的AppBar类似&#xff0c;它们的…

BFS(广度优先搜索)——搜索算法

BFS&#xff0c;也就是广度&#xff08;宽度&#xff09;优先搜索&#xff0c;二叉树的层序遍历就是一个BFS的过程。而前、中、后序遍历则是DFS&#xff08;深度优先搜索&#xff09;。从字面意思也很好理解&#xff0c;DFS就是一条路走到黑&#xff0c;BFS则是一层一层地展开。…

数据库 - Sqlserver - SQLEXPRESS、由Windows认证改为SQL Server Express认证进行连接 (sa登录)

本文讲SqlServer Express版本在登录的时候&#xff0c; 如何由Windows认证&#xff0c;修改为Sql Server Express认证。 目录 1&#xff0c;SqlServer Express的Windows认证 2&#xff0c;修改为混合认证 3&#xff0c;启用sa 用户 4&#xff0c;用sa 用户登录 下面是详细…

GWO优化SVM回归预测matlab

灰狼优化算法&#xff08;Grey Wolf Optimizer&#xff0c;简称 GWO&#xff09;&#xff0c;是由澳大利亚格里菲斯大学的 Mirjalii 等人于 2014 年提出的群智能优化算法。该算法的设计灵感源自灰狼群体的捕食行为&#xff0c;核心思想是对灰狼社会的结构与行为模式进行模仿。 …

elasticsearch8.15 高可用集群搭建(含认证Kibana)

文章目录 1.资源配置2.系统参数优化3.JDK17安装4.下载&安装ES 8.155.生成ES的证书(用于ES节点之间进行安全数据传输)6.修改ES 相关配置文件7.创建es用户并启动8.配置ES的账号和密码(用于ES服务端和客户端)9.下载和安装Kibana10.编辑Kibana配置文件11.启动Kiabana12.访问Kia…

地址查询API接口:高效查询地址信息,提升数据处理效率

地址查询各省市区API接口 地址查询是我们日常生活中经常遇到的一个需求&#xff0c;无论是在物流配送、地图导航还是社交网络等应用中&#xff0c;都需要通过地址来获取地理位置信息。为了满足这个需求&#xff0c;我们可以使用地址查询API接口来高效查询地址信息&#xff0c;提…

3、C#基于.net framework的应用开发实战编程 - 实现(三、三) - 编程手把手系列文章...

三、 实现&#xff1b; 三&#xff0e;三、编写应用程序&#xff1b; 此文主要是实现应用的主要编码工作。 1、 分层&#xff1b; 此例子主要分为UI、Helper、DAL等层。UI负责便签的界面显示&#xff1b;Helper主要是链接UI和数据库操作的中间层&#xff1b;DAL为对数据库的操…

vscode软件操作界面UI布局@各个功能区域划分及其名称称呼

文章目录 abstract检查用户界面的主要区域官方文档关于UI的介绍 abstract 检查 Visual Studio Code 用户界面 - Training | Microsoft Learn 本质上&#xff0c;Visual Studio Code 是一个代码编辑器&#xff0c;其用户界面和布局与许多其他代码编辑器相似。 界面左侧是用于访…

类和对象(下)——类型转化 static成员 内部类 匿名对象 拷贝对象优化

一、类型转换 1.1 类型转化特点 C支持内置类型隐式类型转换为类类型对象&#xff0c;需要有相关内置类型为参数的构造函数。构造函数前面加explicit就不再支持隐式类型转换。类类型的对象之间也可以隐式转换&#xff0c;需要相应的构造函数支持 内置类型转换为类类型对象&#…

基于场景图的零样本目标导航

参考论文&#xff1a;SG-Nav&#xff1a;Online 3D Scene Graph Prompting for LLM-based Zero-shot Object Navigation 0 前言 基于现成的视觉基础模型VFMs和大语言模型LLM构建了无需任何训练的零样本物体巡航框架SG-Nav。 通过VLMs将机器人对场景的观测构建为在线的3D场景图…

开屏广告-跳过神器

给大家介绍一款超实用的软件——SKIP&#xff0c;它堪称李跳跳的最佳平替&#xff01;这款软件已经在Github开源免费&#xff0c;完全无需担心内置源问题&#xff0c;也无需导入任何规则。安装完成后&#xff0c;即可直接使用&#xff0c;非常便捷&#xff01; 首次打开软件时…

大模型本地化部署(Ollama + Open-WebUI)

文章目录 环境准备下载Ollama模型下载下载Open-WebUI 本地化部署的Web图形化界面本地模型联网查询安装 Docker安装 SearXNG本地模型联网查询 环境准备 下载Ollama 下载地址&#xff1a;Ollama网址 安装完成后&#xff0c;命令行里执行命令 ollama -v查看是否安装成功。安装成…

自制虚拟机(C/C++)(三、做成标准GUI Windows软件,扩展指令集,直接支持img软盘)

开源地址:VMwork 要使终端不弹出&#xff0c; #pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") 还要实现jmp near 0x01类似的 本次的main.cpp #include <graphics.h> #include <conio.h> #include <windows.h> #includ…

【游戏设计原理】97 - 空间感知

一、游戏空间的类型 将游戏设计中的空间设计单独提取出来&#xff0c;可以根据其结构、功能和玩家的交互方式划分为以下几种主要类型。这些类型可以单独存在&#xff0c;也可以组合使用&#xff0c;以创造更加复杂和有趣的游戏体验。 1. 线性空间 定义&#xff1a;空间设计是…

基于开源AI智能名片2 + 1链动模式S2B2C商城小程序视角下的个人IP人设构建研究

摘要&#xff1a;本文深入探讨在开源AI智能名片2 1链动模式S2B2C商城小程序的应用场景下&#xff0c;个人IP人设构建的理论与实践。通过剖析个人IP人设定义中的“诉求”“特质”“可感知”三要素&#xff0c;结合该小程序特点&#xff0c;阐述其对个人IP打造的影响与推动作用&…

数据库和数据表的创建、修改、与删除

1.标识符命名规则 数据库名、表名不得超过30个字符&#xff0c;变量名限制为29个 必须只能包含A-Z,a-z,0-9,_共63个字符 数据库名、表名、字段名等对象名中间不能包含空格 同一个MySQL软件中&#xff0c;数据库不能同名&#xff1b;同一个库中&#xff0c;表不能重名&#…

算法日记10:SC62求和(单调栈)(共享求解)

一、题目 二、题解&#xff1a; 1、首先&#xff0c;我们看到题目的第一个想法&#xff0c;就是把样例答案如何求解给列出来&#xff0c;图例如下 2、通过分析样例&#xff0c;可以很清晰的发现每一个数字都有其管辖的区间&#xff0c;因此我们可以想到能否找到一个数字它所管…

Revit二次开发 自适应族添加放样融合

大多数博客给出的方案都是如何在有自适应族的情况下进行修改定位点或是将数据传入自适应族,如何直接在族文件中创建自适应模型并将点转换为自适应点,连接自适应点成为自适应路径这种方式没有文章介绍. 下面的代码中给出了如何在自适应族文件中创建参照点并转换为自适应点连接…

基于VMware的ubuntu与vscode建立ssh连接

1.首先安装openssh服务 sudo apt update sudo apt install openssh-server -y 2.启动并检查ssh服务状态 到这里可以按q退出 之后输入命令 &#xff1a; ip a 红色挡住的部分就是我们要的地址&#xff0c;这里就不展示了哈 3.配置vscode 打开vscode 搜索并安装&#xff1a;…

解决SetWindowCompositionAttribute使控件文本透明的问题

用以下参数调用该API&#xff0c;能实现类似Aero的模糊透明效果。 参数具体含义见 https://zhuanlan.zhihu.com/p/569258181 http://www.memotech.de/WindowComposition/Text.txt http://www.memotech.de/WindowComposition/WindowComposition.zip DWORD accent[4] { 3,0,0,0 …