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

【Java学习笔记】18.反射与注解的应用

反射为Java程序在运行时提供了动态的能力,而注解允许通过一定的方式编写描述类的元数据。这些元数据可以为编译器提供信息,也可以进入字节码文件在运行时使用。这一章,将详细介绍这两种特性的原理与使用。

1.反射

反射是Java语言提供的一项非常吸引人的特性。利用反射可以在运行时对程序进行动态的控制,开发使用反射特性的程序需要使用一套专门的工具类,这些类大部分位于java.lang.reflect包中。

2.Class类的使用实例

Class类属于java.lang包,不需要使用import语句引入特殊的包就能使用,其对象代表一个类,携带相应的信息,主要包括构造器、方法、成员变量等。其实在Java程序运行的过程中,每个类被加载后都在内存中产生一个对应的Class类对象,在普通应用程序中这些对象由系统自动维护,不需要开发人员关心。
提示:Class类中,“C”为大写,如果小写就变成了声明类的Java的关键字。

Class类提供了很多用来加载及获得对应信息的方法。

在这里插入图片描述
在这里插入图片描述

注意:

  1. 不可以使用Class类的构造器来创建Class类对象,只能使用其提供的静态工厂方法来获取对象
  2. Field、Method、Constructor为java.lang.reflect包中的类,他们的对象分别代表成员变量、方法、构造器的信息
  3. package类在java.lang包中,其对象代表一个包,携带包的相应信息、

【例1】Class类的简单使用


//用来被加载类的父类
class MyFather {//父类的公共成员变量public int memerFather;//父类的公共方法public void methodFather() {System.out.println("我是从父类继承过来的方法");}}class MySon extends MyFather{//子类的公共成员变量public int memerSonPulic;//子类的私有成员变量private int memerSonPrivate;//子类的私有方法public void methodSonProtected() {System.out.println("我是子类自己的方法methodSonProtected");}//子类的公共方法public void methodSonPulic() {System.out.println("我是子类自己的方法methodSonPulic");}}//主类
public class Sample31_1 {public static void main(String[] args) {try {//加载指定的类Class c=Class.forName("org.example.MySon");//创建加载类的对象MySon ms = (MySon)c.newInstance();//调用创建对象的方法System.out.println("========调用创建对象的方法==========");ms.methodSonProtected();ms.methodSonPulic();ms.methodFather();//打印类的详细信息System.out.println("========打印类的Class信息==========");System.out.println(c.getName()+"类自己声明了"+c.getDeclaredFields().length+"个成员变量");System.out.println(c.getName()+"类对外公布的方法有"+c.getMethods().length+"个.");}catch(Exception e){e.printStackTrace();}}
}

在这里插入图片描述

  • 定义了两个类,MySon&MyFather,其中MySon继承自MyFather,两个类中各种有一些方法与成员变量。

  • 在主方法中首先加载了MySon类,然后通过Class对象的newInstance()方法创建了对象,并调用了对象中的方法,最后打印了加载类的信息。
    -调用newInstance()方法创建对象后,返回的是Object类型的引用,需要进行恰当的强制类型转换才能够当做具体类型使用。

  • 通过newInstance()方法创建的对象与通过普通方式创建的对象在使用上完全相同。

  • 通过Class类可以获得所加载类的信息,打印出的信息与MySon类的具体情况是符合的。
    - 因为还有从Object类间接继承而来的方法,所以打印出来MySon对外公布的方法有11个。

想要获取一个类对应的Class对象不一定要用forName()方法进行加载,java.lang.Oject类就提供了一个名为getClass()的方法来获取对象所在类对应的Class对象,方法签名如下:

public final Class getClass()

因为此方法时pulic类的,而Object类是Java中所有类的父类,因此所有类的对象都可以使用这个方法。

【例2】Class类的简单使用

package org.example;//用来被加载类的父类
class MyFather {//父类的公共成员变量public int memerFather;//父类的公共方法public void methodFather() {System.out.println("我是从父类继承过来的方法");}}class MySon extends MyFather{//子类的公共成员变量public int memerSonPulic;//子类的私有成员变量private int memerSonPrivate;//子类的私有方法public void methodSonProtected() {System.out.println("我是子类自己的方法methodSonProtected");}//子类的公共方法public void methodSonPulic() {System.out.println("我是子类自己的方法methodSonPulic");}}//主类
public class Sample31_1 {public static void main(String[] args) {MyFather mf = new MyFather();//加载指定的类Class c=mf.getClass();//打印类的详细信息System.out.println("========加载类"+c.getName()+"的信息==========");System.out.println(c.getName()+"类自己声明了"+c.getDeclaredFields().length+"个成员变量");System.out.println(c.getName()+"类对外公布的方法有"+c.getMethods().length+"个.");//创建加载类的对象MySon ms = new MySon();//获取class对象c = ms.getClass();//打印类的详细信息System.out.println("========加载类"+c.getName()+"的信息==========");System.out.println(c.getName()+"类自己声明了"+c.getDeclaredFields().length+"个成员变量");System.out.println(c.getName()+"类对外公布的方法有"+c.getMethods().length+"个.");}}

在这里插入图片描述
通过getClass()方法,也可以获得类对应的class对象。

3. 数组与Class类

Java中的数组是对象,因此数组对象也可以调用getClass()方法获取其对应的Class对象
【例】

package service;import java.io.File;
import java.io.Reader;
import java.util.Properties;public class Test {public static void main(String[] args) {//创建数组对象String[] stringArray = new String[4];int[][] intArray = new int[9][9];//获取数组对应的Class类Class sc = stringArray.getClass();Class ic = intArray.getClass();//打印两个类对应的类名System.out.println("一维String数组对应的类名为:"+sc.getName()+"。");System.out.println("二维int数组对应的类名为"+ic.getName()+"。");}
}

在这里插入图片描述

  • 数组对象也有他们对应的类,类名是[Ljava.lang.String; [[I
  • 以‘[’开头的是数组,两个‘[’代表二维数组,几维数组后有几个‘[’
  • 如果是对象引用型数组,则表示在维数的几个‘[’后面跟上"L<类名>",例:三维Oject数组对应的类名为’[[[Ljava.lang.Object;'。
  • 如果是基本类型数组,则在表示维数的’['后跟上“<类型代号>”,如 二维boolean型数组对应的类名为"[[Z"
基本类型 代号
boolean Z
byte B
short S
char C
int I
long J
double D
float F

数组对应的类比较特殊,没有提供可用的构造器,因此无法直接使用Class类提供的静态工厂方法newInstance()来创建对象。

4. 精准判断对象类型

instanceof关键字无法用来判断对象的精确类型,如果需要判断对象的精确类型,就需要使用反射技术。

package reflect;//
http://www.xdnf.cn/news/1352341.html

相关文章:

  • 遥感机器学习入门实战教程|Sklearn案例⑧:评估指标(metrics)全解析
  • tcpdump命令打印抓包信息
  • 【golang】ORM框架操作数据库
  • 2-5.Python 编码基础 - 键盘输入
  • STM32CubeIDE V1.9.0下载资源链接
  • 醋酸镨:催化剂领域的璀璨新星
  • LangChain4J-基础(整合Spring、RAG、MCP、向量数据库、提示词、流式输出)
  • 信贷模型域——信贷获客模型(获客模型)
  • 温度对直线导轨的性能有哪些影响?
  • 小白向:Obsidian(Markdown语法学习)快速入门完全指南:从零开始构建你的第二大脑(免费好用的笔记软件的知识管理系统)、黑曜石笔记
  • 数字经济、全球化与5G催生域名新价值的逻辑与实践路径
  • 快速掌握Java非线性数据结构:树(二叉树、平衡二叉树、多路平衡树)、堆、图【算法必备】
  • vue3 - 组件间的传值
  • 【小沐学GIS】基于Godot绘制三维数字地球Earth(Godot)
  • 计算机网络 TLS握手中三个随机数详解
  • 【Golang】有关垃圾收集器的笔记
  • 语义通信高斯信道仿真代码
  • GaussDB 数据库架构师修炼(十八) SQL引擎-计划管理-SQL PATCH
  • Base64编码、AES加密、RSA加密、MD5加密
  • RAG Embeddings 向量数据库
  • 使用Ollama部署自己的本地模型
  • 疯狂星期四文案网第48天运营日记
  • 12 SQL进阶-锁(8.20)
  • Python语法速成课程(二)
  • 科技赋能,宁夏农业绘就塞上新“丰”景
  • 进程的概念:进程调度算法
  • 【GPT入门】第57课 详解 LLamaFactory 与 XTuner 实现大模型多卡分布式训练的方案与实践
  • rust语言 (1.88) egui (0.32.1) 学习笔记(逐行注释)(七) 鼠标在控件上悬浮时的提示
  • linux中文本文件操作之grep命令
  • 【软件设计模式】策略模式