反射的基础部分知识

news2024/12/22 20:46:09

反射的基础——Class

Java当中的类用来表示具有相同属性和方法的对象的集合,是抽象的概念。对象是类创建的,同一个类的不同对象具有不同的属性值。

Java当中定义的所有类都属于同一类事物,可以Class来表示。

类型

访问方法

返回值类型

说明

包路径

getPackage()

Package 对象

获取该类的存放路径

类名称

getName()

String 对象

获取该类的名称

继承类

getSuperclass()

Class 对象

获取该类继承的类

实现接口

getlnterfaces()

Class 型数组

获取该类实现的所有接口

构造方法

getConstructors()

Constructor 型数组

获取所有权限为 public 的构造方法

getDeclaredContruectors()

Constructor 对象

获取当前对象的所有构造方法

方法

getMethods()

Methods 型数组

获取所有权限为 public 的方法

getDeclaredMethods()

Methods 对象

获取当前对象的所有方法

成员变量

getFields()

Field 型数组

获取所有权限为 public 的成员变量

getDeclareFileds()

Field 对象

获取当前对象的所有成员变量

对比理解:

不同的人可以用Person类来表示。

人->Person

Java当中定义的不同类可以用Class来表示。

Java当中的类->Class

Class类的对象-字节码:不同类编译生成的字节码。

Person p1 = new Person();

Class class = new Class()       (×)

三种方式:

  1. 对象名.getClass()

Person p1 = new Person(); p1.getClass();

  1. 类名.class

Date.class

  1. Class.forName()方法(此方式用的较多)

Class.forName(“java.lang.String”);

package com.apesource.demo;
//class对象的三种创建方式
public class Demo01 {
	public static void main(String[] args) throws ClassNotFoundException {
		//方法1:通过类名访问class 
		Class stringCls = String.class;
		//方法2: 通过实例访问getclass();
		String s = "";
		Class stringCls2 = s.getClass();
		//方法3:通过class类的静态方法forName(类名)
		Class stringCls3 = Class.forName("java.lang.String");
		
		
		System.out.println(stringCls.getName());
		System.out.println(stringCls2.getName());
		System.out.println(stringCls3.getName());

	}

}

Java当中的基本数据类型有:

Boolean int short byte char long float 和 double 他们也有各自的Class对象。

例如:int.class

Void 也有自己对应的Class对象 void.class

基本数据类型对应的封装类有属性TYPE,这个属性代表了封装所封装的基本数据类型的Class对象。

反射就是把Java类中的各个组成部分映射成相应的Java类。

一个类的组成部分包括:属性,方法,构造方法,包等。这些组成部分都会被映射成相应的类。

Class类定义了一系列方法来获取java类的属性,方法,构造方法,包等信息,这些信息都有相应的类来表示,分别是Field,Method,Constryctor,Package等。

注意:表示java类组成部分的各种类位于java.lang.reflect包中

Constructor类

Constructor类用来描述类中所定义的构造方法。

(1)得到类所有的构造方法

Constructor constructors[]=

Class.forName(java.lang.String).getConstructors();

  1. 得到类中某个具体的构造方法,在getConstructors中传入参数类型所对应的字节码

Constructor constructor=

Class.forName(java.lang.String).getConstructor(String.class)

使用Constructor类的目的是用来创建响应类的对象

正常情况:

String str = new String(“hello”);

反射情况:

Constructor con = String.class.getConstructor(String.class)

//拿到string类型的构造方法

String str = (String)con.newlnstance(“hello”)

通过反射方式创建对象的过程

Class---->Constructor---->某个类的对象

只有当要用某个无参构造方法创建该类对象时,可以省略创建Constructor类对象的这个过程。

Date d = (Date)Class.forName(“java.util.Date”).newlnstance();

注意:java运行环境的缓存中保存了类的无参构造方法所对应的Constructor对象。

Field类

Field类用来表示类中的属性(字段)。

(1) Class.getPields0:得到Class对象的所有字段,返回的是riela数组。

(2) Class. getField (String: name)返回个 Field 对象,它反映此 Class对象所表示的类或接口的指定公有成员字段。

(3) Field的对象所代表的某-一个类的属性,而不是那个类的某一个对象的属性。要得到某个对象对应的属性值,需要通过get (0b ject obj)方法与某个对象具体关联

(4)对于非公有属性只能通过Class的getDec laredField (String fieldName)方法得到。

(5)对于私有属性要得到它所关联到的对象的值,需通过Field的setAccessible (boolean boolean)方法设置。

(6) Field类的getType Q方法用来得到字段所属的类型

动态加载机制

public class Main {
    static {
		System.out.println("Main被加载");
	}
	public static void main(String[] args) {
		int rand = new Random().nextInt(10);
        if (rand > 5) {
            create(rand);
        }
    }

    static void create(int no) {
    	Person p = new Person(no);
    }
}

class Person{
	
	static {
		System.out.println("Person类被加载");
	}
	
	public Person(int no) {
		System.out.println("Person类的有参构造方法");
	}
}

当执行Main.java时,由于用到了Main,因此,JVM首先会把Main.class加载到内存。然而,并不会加载Person.class,除非程序执行到create()方法,JVM发现需要加载Person类时,才会首次加载Person.class。如果没有执行create()方法,那么Person.class根本就不会被加载。

Method类

Method用来表示类中的方法。通过Class对象的如下方法得到Method对象:

  1. Method getMethod(String name,Class<?>…parameterTypes)按名称得到某个特定的public方法(包括从父类或者接口继承的方法);
  2.  Method[] getMethods():得到public方法(包括从父类或者接口继承的方法);
  3. Method[] getDeclaredMethods():得到所有的方法(不包括继承的方法);
  4. Method getDeclaredMethod(String name,Class<?>…parame-

terTypes):按名称得到某个特定的方法(不包括继承)。

得到某个方法对应的Method对象后,需要调用如下方法来在某个对象上执行该方法:

  1. invoke(Object obj,Object…obj)方法用来调用Method所表示的方法。其中,第一个参数表示此方法作用于哪一个对象。
  2. 如果调用的时静态方法,那么invoke()方法中的第一个参数用null表示。
//获得共有方法
Method method[] = class1.getMethods();
for (Method mm : method){
    System.out.println("共有方法的名称是"+mm.getName());
}

 当参数为数组时

Method method4 = class1.getDeclaredMethod("showMessages", String[].class);
        System.out.println("得到的这个方法是:"+method4.getName());
        String[] strs = {"你好","咸阳师范学院","计算机学院"};
//        1,调用数组的参数方法,把整个实际的数组最为一个Object数组的唯一元素进行调用
        method4.invoke(person1,new Object[] {strs});

//        2,吧实际数组转换为Object对象
        method4.invoke(person1,(Object)strs);

 

  1. 得到Method对象的最终目的还是为了去调用这个方法;
  2. 如果要执行应该私有访问权限的方法,调用该方法执行要执行setAccessible方法,设置为true;
  3. 调用数组的参数方法,把整个实际的数组最为一个Object数组的唯一元素进行调用;
  4. 最后将把实际数组转换为Object对象;
  5. 数组也是符合数据类型。
  6. Method类-关于方法参数的操作

  7. int getParameters():获取该Method对象所表示方法的参数数量;
  8. Parameter[] getParameters():返回一个Parameter对象的数组,表示该Method对象所表示方法返回的所有参数;
  9. Class<?>[] getParameterTypes():获取该Method对象所表示方法的所有参数类型的数组;
  10. Type[] getGenericParameterTypes():获取该Method对象所表示方法的所有参数类型的数组,一般情况下,同getParameterTypes()方法的返回值一样,如果存在泛型,则该方法会返回泛型的类型。
(5)public class MethodReflect {
    public static void main(String[] args) {

        Class<? extends MyClass1> aClass = MyClass1.class;

        Method[] methods = aClass.getDeclaredMethods();
        for (Method method : methods){
            //获取该方法的参数值
            int parameterCount = method.getParameterCount();
            //获取参数类型数组,
            Class<?>[] parameterTypes = method.getParameterTypes();
            Type[] genericParameterTypes = method.getGenericParameterTypes();
            for (int i = 0;i < parameterTypes.length; i++){
                System.out.println(method.getName()+","+parameterCount+","+parameterTypes[i].getTypeName()+","+genericParameterTypes[i].getTypeName()+"\t");
            }
            System.out.println();
        }
    }
}
class MyClass1{
    public void m1(int i){

    }

    public void m2(Boolean bool){

    }

    public void m3(String str,int i){

    }

    public void m4(List<String> list){

    }

    public void m5(Integer... nums){

    }
}

 

Method类-关于方法返回值的操作

  1. Class<?> getReturnType():返回应该Class对象,该对象表示此Method对象表示的方法的正式返回值类型;
  2. Type getGenericReturnType():返回一个Type对象,该对象表示此Method对象表示的方法的正式返回值类型。(如果返回值类型不是泛型,那么两个方法的返回值是一致的;如果是泛型,getGenericReturnType()方法会返回泛型的类型。)
(3)public class MethodReflect2 {
    public static void main(String[] args) {

        Class<? extends MyClass2> aClass = MyClass2.class;

        Method[] methods = aClass.getDeclaredMethods();
        for (Method method : methods){
            Class<?> returnType = method.getReturnType();
            Type genericReturnType = method.getGenericReturnType();
            System.out.println(returnType+","+genericReturnType);
        }

    }
}

class MyClass2{

    public int getInt(){
        return 1;
    }

    public Boolean getBoolean(){
        return Boolean.TRUE;
    }

    public String getString(){
        return "ddc";
    }

    public List<String> getList(){
        return new ArrayList<>();
    }

    public Map<String,Object> getMap(){
        return new HashMap<>();
    }
}

Method类-关于修饰符

  1. int getModifiers():得到方法前面所定义的修饰符,返回类、接口、变量、方法等以2整数编码的Java语言修饰符,访问修饰符编码列表。Modifier类应该提供了12种修饰符的编码常量;
  2. java.lang.reflect.Modifier类提供解码类和访问修饰符的静态方法和常量,系师傅集合别表示为具有表示不同的修饰符的不同位置的整数。

Method类-关于修饰符

  1. int getModifiers():得到方法前面所定义的修饰符,返回类、接口、变量、方法等以2整数编码的Java语言修饰符,访问修饰符编码列表。Modifier类应该提供了12种修饰符的编码常量;
  2. java.lang.reflect.Modifier类提供解码类和访问修饰符的静态方法和常量,系师傅集合别表示为具有表示不同的修饰符的不同位置的整数。

Method类-关于所抛出的异常

  1. Class[] method.getExceptionTypes():方法在定义的时候可以通过throws关键字声明抛出异常,应该方法可以抛出多个异常。

数组的反射操作

在Java中数组属于符合数据类型,具有相同元素类型和维数的数组属于同一个类型,即具有相同的字节码对象。

代表数组的字节码对象调用getSuperClass()得到它的父类Object的字节码对象。

基本数据类型的一维数组可以当做Object类型使用,但不能当作Object[]类型使用;基本数据类型的二维数组可以当做Object[]类型使用;复合数据类型的一维数组既可以当做Object类型使用,也可以当作Object[]类型使用。

Java.lang.Array用于完成对数组的反射操作。

Object[]来使用
//数组也是复合类型
Object obj3 = new String[4];//一维复合数据类型数组当作Object使用
Object[] obj4 = new String[4];//一维复合数据类型数组当作Object[]使用

Object[][] obj5 = new String[4][5];//二维复合数据类型数组当作Object,Object[][].或者Object[]使用

int a1[] = new int[3];
int a2[] = new int[100];
//只要维数相等,类型相等,那么我们就认为驻足的class对象相等(和元素个数无关)
System.out.println(a1.getClass() == a2.getClass());
  1. 只要维数相等,类型相等,那么我们就认为驻足的class对象相等(和元素个数无关);
  2. 二维复合数据类型数组当作Object,Object[][].或者Object[]使用;

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

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

相关文章

MySQL数据库管理(二)

文章目录 一.表结构(增加字段)1.创建表结构2.复制数据表2.1 复制格式2.2 克隆表 3.清空表&#xff0c;删除表内的所有数据4.创建临时表 二.MySQL中6种常见的约束1.外键的定义2.创建外键约束作用3.创建主表blue4.创建从表Icecream5.为主表blue添加一个主键约束。主键名建议以&qu…

JAVA - 内存管理

目录 内存管理是什么 JVM内存区域组成 程序计数器PC java虚拟机栈 本地方法栈 JAVA堆 方法区 常量池 运行时常量池 内存管理是什么 Java的内存管理就是对象的分配和释放问题 分配 &#xff1a;内存的分配由程序完成的&#xff0c;程序员通过关键字new 为每个对象申请…

mysql视图的简单应用

1、创建一视图 stu_info,查询全体学生的姓名&#xff0c;性别&#xff0c;课程名&#xff0c;成绩。 create view stu_info(姓名,性别,课程名,成绩) as select Sname,Ssex,Cname,Score from Course,SC,Student where Student.Sno SC.Sno and SC.Cno Course.Cno;去查看视图 …

混合云监控

混合云基础架构的增长是由增强的灵活性、成本优化机会以及对敏捷 DevOps 文化的支持等优势推动的。另一方面&#xff0c;在混合云环境中很难实现可见性、问责制和控制&#xff0c;这被证明是混合云成功的障碍。尽管公共云提供商提供了用于监控服务可用性的控制台&#xff0c;但…

将媒体公司资产迁移到 Amazon S3 的技术方案

随着媒体公司的发展&#xff0c;他们在仓库中积累了大量的旧磁带和未数字化的视频。这些资产可能很有价值&#xff0c;但以目前的形式很难访问和货币化。此外&#xff0c;将这些资产存储在仓库中既有风险又昂贵。 媒体企业可以通过将其资产迁移到云存储来解决这些问题&#xf…

MySQL练习题(5)

创建表并插入数据 1、创建一个可以统计表格内记录条数的存储函数 &#xff0c;函数名为count_sch() select count_sch() 2、创建一个存储过程avg_sai&#xff0c;有3个参数&#xff0c;分别是deptno&#xff0c;job&#xff0c;接收平均工资&#xff0c; 功能查询emp表dept为30…

开放式蓝牙耳机测评!2023年值得入手的开放式蓝牙耳机都在这里!索尼、南卡、韶音、飞利浦等等品牌,看看有没有适合你的款式!

这可能是站内最详细的开放式蓝牙耳机选购攻略&#xff01;想入手开放式蓝牙耳机必看&#xff01; 在这个人人手机不离手的快节奏时代&#xff0c;蓝牙耳机自然是越多越多人的选择&#xff0c;而随着耳机种类的进化代送&#xff0c;开放式蓝牙耳机&#xff0c;也随之被大众熟知…

【面试题39】能够使HTML和PHP分离开使用的模板技术有哪些

文章目录 一、前言二、模板技术的好处三、常用的模板技术3.1 PHP模板引擎3.2 前端模板引擎3.3 前后端分离技术 四、Smarty模板使用演示4.1 在项目中引入Smarty模板引擎的文件4.2 引入Smarty.class.php文件4.3 创建一个Smarty对象4.4 变量定义4.5 创建一个Smarty模板文件4.6 绑定…

无需魔法三分钟上线Midjourney应用,【附源码】【示例】

ps:我是标题党&#xff0c;目前还没见过三分钟完成任务的&#xff0c;三分钟只能打通Midjourney接口。我花了一天时间接入应用哈哈哈&#xff01; 首先&#xff0c;我要感谢laf赞助我&#xff0c;让我可以免费使用Midjourney进行开发和测试。来自白嫖党的快乐。 其次&#xff…

基于linux下的高并发服务器开发(第一章)- 静态库和动态库的对比1.9

01 / 程序编译成可执行程序的过程 静态库、动态库区别来自链接阶段如何处理&#xff0c;链接成可执行程序。分别称为静态链接方式和动态链接方式。 02 / 静态库的制作过程 03 / 动态库的制作过程 04 / 静态库的优缺点 05 / 动态库的优缺点

[工具推荐] LICEcap 动图gif录制工具 轻量/开源/免费

先声明&#xff1a;不是广子&#xff0c;单纯分享 LICEcap 之前用Windows时&#xff0c;就用这个软件 后来用mac了&#xff0c;发现它也有mac版的&#xff0c;也支持m1芯片的苹果电脑 这是目前用过最轻量的gif录制软件了&#xff0c; 程序整体都不到1mb 该有的功能都有&a…

『表面』无序点云的快速三角化

1、PCL中的贪婪投影三角化&#xff08;GreedyProjectionTriangulation&#xff09;算法 该算法用于将无序点云数据转换为表面三角网络模型的表面重建算法。可以根据点云数据中的几何信息&#xff0c;自动构建出具有连续性和平滑性的三角网络模型。 具体步骤&#xff1a; 预处…

马斯克在与创业公司OpenAI竞争的新竞标中公布了xAI

北京时间7月13日凌晨&#xff0c;马斯克在Twiiter上毫无预警地宣布&#xff1a;“xAI正式成立&#xff0c;去了解现实。”&#xff08;Announcing formation of xAI to understand reality.&#xff09;这是马斯克首次官宣xAI的进展。 xAI的Twitter账号中目前还没有多少内容&a…

嵌入式Linux开发实操(四):pinctrl和dt_binding

Linux/pinctrl subsystem,统一了各SOC/MCU厂商的PIN引脚管理了吗? pin命名遵循IC spec上的命名。它是如何实现驱动到硬件的对接的呢?在CPU、Memory等完成初始化加载之后,显然就进入到了嵌入式linux的核心部分,管理对接硬件,这正是pinctrl要完成的工作。 Linuxpinctrl架构…

el-date-picker 日期时间进行限制,精确到时分秒

需求&#xff1a;用户只能选择当时时间或当前时间之前的时间&#xff0c;且精确到时分秒 实现效果&#xff1a;用户只能选择当前时间的时间&#xff0c;如果选择是当天之前的时间&#xff0c;时分秒不做限制&#xff0c;如果选择的是当天时间&#xff0c;就要判断时分秒&#…

Stable Diffusion 丝滑无闪烁AI动画 Temporalkit+Ebsynth+Controlnet

早期的EbSynth制作的AI视频闪烁能闪瞎人的双眼,可以通过【temporalkit+ebsynth+controlnet】让视频变得丝滑不闪烁。 文章目录 插件准备丝滑视频制作插件准备 下载安装 EbSynth官网,这里需要输入email地址。 下载压缩包解压缩到任意位置,这里我放到了ebsynth_utility下。 …

Flowable边界事件-消息边界事件

消息边界事件 消息边界事件一、定义1. 图形标记2. 设置消息 选择消息3. XML标记 二、测试用例2.1 定时边界事件xml文件2.2 消息边界事件测试用例 总结 消息边界事件 一、定义 接收到消息触发事件 1. 图形标记 2. 设置消息 选择消息 3. XML标记 定时边界事件的XML <messag…

【sgWaterfall】Vue实现图文瀑布流布局模式,图片预加载显示占位区域阴影,加载完成后向上浮动动画出现

Vue实现图文瀑布流布局模式&#xff0c;图片预加载显示占位区域阴影&#xff0c;加载完成后向上浮动动画出现 sgWaterfall.vue源码 <template><ul :class"$options.name" :style"waterfallStyle"><li v-for"(a, i) in items "…

业务变革与架构双驱动的多项目管理︱海康威视流程变革咨询顾问张燕飞

海康威视数字技术股份有限公司流程与变革管理部流程变革咨询顾问张燕飞女士受邀为由PMO评论主办的2023第十二届中国PMO大会演讲嘉宾&#xff0c;演讲议题&#xff1a;业务变革与架构双驱动的多项目管理。大会将于8月12-13日在北京举办&#xff0c;敬请关注&#xff01; 议题简要…

如何在MySQL中安装示例数据库sakila

就像 SQLServer 示例数据库一样,MySQL 也有示例数据库,比如sakila;Sakila 数据库最初由 MySQL AB 文档团队的前成员 Mike Hillyer 开发,旨在提供一个标准模式,可用于书籍、教程、文章、示例等中的示例,它包含示例视图、存储过程和触发器。 以下是在服务器上安装sakila数…