当前位置: 首页 > 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.dtcms.com/a/347181.html

相关文章:

  • [e3nn] 模型部署 | TorchScript JIT | `@compile_mode`装饰器 | Cython
  • TypeScript的构造函数constructor用法理解
  • 深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)第四章知识点问答补充及重新排版
  • 离线优先与冲突解决:ABP vNext + PWA 的边缘同步
  • SQL Server更改日志模式:操作指南与最佳实践!
  • 使用 Certbot 申请 Apache 证书配置棘手问题
  • UAD详解
  • 分库分表系列-核心内容
  • 知识蒸馏 Knowledge Distillation 概率链式法则(Probability Chain Rule)
  • Class42时序模型
  • 深度学习开篇
  • 【通俗易懂】TypeScript 的类型守卫 (Type Guards)作用理解
  • iperf2 vs iperf3:UDP 发包逻辑差异与常见问题
  • [新启航]白光干涉仪与激光干涉仪的区别及应用解析
  • ubuntu 新登录修改root密码
  • 【攻防世界】Web_php_include
  • 力扣热题之动态规划
  • CryptSIPVerifyIndirectData函数分析
  • 鸿蒙开发进阶(HarmonyOS)
  • STM32 外设驱动模块八:红外反射式光电模块
  • 【大语言模型 15】因果掩码与注意力掩码实现:深度学习中的信息流控制艺术
  • 2-5.Python 编码基础 - 键盘输入
  • 2025钉钉十周年新品发布会,新品 “蕨”命名,到底是什么?
  • vue3 - 组件间的传值
  • nodejs和vue安装步骤记录
  • 【Golang】有关任务窃取调度器和抢占式调度器的笔记
  • 机器人 - 无人机基础(5) - 飞控中的传感器(ing)
  • 【大语言模型 16】Transformer三种架构深度对比:选择最适合你的模型架构
  • 云原生俱乐部-k8s知识点归纳(8)
  • 资深产品经理个人能力提升方向:如何系统化进阶并考取高价值证书?