java中的反射和Class类

news2024/11/26 20:21:11

动态语言 VS 静态语言:

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

静态语言与动态语言相对应的运行时结构不可改变的语言就是静态语言,如JAVA,C,C++

JAVA不是动态语言,但JAVA可以称之为"准动态语言”,即JAVA具有一定的动态性,我们可以利用反射机制获得类似动态语言的特性,JAVA的动态性让编程的时候更加灵活。

反射的概念:

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

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

Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建,加载完之后再堆内存的方法,其中就产生了一个Class类型的对象,一个类只有一个Class对象,这个对象就包含了完整的类的结构信息,我们可以通过这个对象看到类的结构,这个对象就像一面镜子,透过这个镜子可以看到类的结构,所以我们形象的称之为反射.
在这里插入图片描述

反射机制所提供的功能:

在这里插入图片描述

反射的优/缺点:

优点:

可以实现动态创建对象和编译,体现出很大的灵活性.

缺点:

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

通过反射机制获取Class类:

Class.forName()方法:

1.是个静态方法

2.方法的参数是一个字符串

3.字符串需要的是一个完整的类名

4.完整类名必须带有包名

举例:

package Collections;
import java.lang.annotation.*;
public class reflect{
 public static void main(String[]args) throws ClassNotFoundException {
     Class class1=Class.forName("Collections.person");
     System.out.println(class1);
     Class class2=Class.forName("Collections.person");
     Class class3=Class.forName("Collections.person");
     Class class4=Class.forName("Collections.person");
     System.out.println(class1.equals(class2));
     System.out.println(class2.equals(class3));
     System.out.println(class3.equals(class4));
     System.out.println(class1.hashCode());
     System.out.println(class2.hashCode());
     System.out.println(class3.hashCode());
     System.out.println(class4.hashCode());
 }
}

输出:

class Collections.person
true
true
true
363771819
363771819
363771819
363771819

通过比较class1-class4,以及输出他们的hashcode是完全相同的,这表明一个类只有一个Class对象,这个对象就包含了完整的类的结构信息。

Class类:

Class类的特点:

java有两种对象:实例对象和Class对象其实我们的实例对象就通过Class对象来创建的每一个类都有一个Class对象,每当编译一个新类就产生一个Class对象。

1:Class本身也是一个类

2Class对象只能由系统建立对象

3:一个加载的类在JVM中只会有一个Class实例

4:一个Class对象对应的是一个加载到JVM中的一个.class文件

5:每个类的实例都会记得自身是由那个Class实例所生成的

6:通过Class可以完整地得到一个类中的所有被加载的结构

7Class类是Reflection的根源,针对任何你想动态加载,运行的类,唯有先获得相应的Class对象。

Class 没有公共构造方法,Class 对象是在加载类时由Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象,也就是说,它并不能通过new的方式创建对象

虚拟机为每种类型管理一个独一无二的Class对象,也就是说,每个类(型)都有一个Class对象,运行程序时,Java虚拟机(JVM)首先检查是否所要加载的类对应的Class对象是否已经加载,如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。

getClass():

public final Class getClass()

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

package Collections;
import java.lang.annotation.*;
public class reflect{
    public static void main(String[]args) throws ClassNotFoundException {
        Class class1=Class.forName("java.lang.Integer");
        Class class2=Class.forName("java.util.Date");
        Class class3=Class.forName("java.lang.String");
        System.out.println(class1);
        System.out.println(class2);
        System.out.println(class3);
        System.out.println(class1.equals(class2));
        System.out.println(class2.equals(class3));
        System.out.println(class1.hashCode());
        System.out.println(class2.hashCode());
        System.out.println(class3.hashCode());
    }
}

输出:

class java.lang.Integer
class java.util.Date
class java.lang.String
false
false
363771819
2065951873
356573597

基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也都对应一个 Class 对象,每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和相同维数的数组都共享该 Class 对象,一般某个类的Class对象被载入内存,它就用来创建这个类的所有对象。

Class类常用的方法:

在这里插入图片描述

获取Class类的实例:

在这里插入图片描述

获得同一个Class对象的不同方法:

方式一:通过对象获得

类名.getClass();

方式二:通过forName获得

Class.forName("包名.类名");

方式3:通过类名.class获得

类名.class;

方式4:通过type属性获得[只能针对于基本内置类型的包装类]

基本内置类型.type;

获得父类类型:

Class类对象.getSuperclass();

举例:

package Collections;

public class text1 {
public static void main(String[]args) throws ClassNotFoundException {
    person1 person1=new Student();
    System.out.println("这个人是:"+person1.name);
    Class c1=person1.getClass();//方式一:通过对象获得
    System.out.println("c1的hashcode为:"+c1.hashCode());
    Class c2=Class.forName("Collections.Student");//方式二:通过forName获得
    System.out.println("c2的hashcode为:"+c2.hashCode());
    Class c3=Student.class;//方式3:通过类名.class获得
    System.out.println("c3的hashcode为:"+c3.hashCode());
    System.out.println("c1和c2相等吗?"+c1.equals(c2));
    System.out.println("c2和c3相等吗?"+c2.equals(c3));
    System.out.println("c1和c3相等吗?"+c1.equals(c3));
    Class c4=c1.getSuperclass();
    System.out.println(c4);
}
}
class person1{
   public String name;

    public person1(String name) {
        this.name = name;
    }

    public person1() {
    }
}
class Student extends person1{
    public Student() {
        this.name="学生";
    }
}
class teacher extends person1{
    public teacher() {
        this.name="老师";
    }
}

输出:

c1的hashcode为:2065951873
c2的hashcode为:2065951873
c3的hashcode为:2065951873
c1和c2相等吗?true
c2和c3相等吗?true
c1和c3相等吗?true
class Collections.person1

通过输出结果,我们可以得出一个结论,无论使用上述三种不同方法中的哪一个均可获得同一个Class对象,即使c1/c2/c3为不同的Class对象,但他们的Class类是同一个。

那些类型可以有Class对象?

在这里插入图片描述简单应用:

package Collections;
import java.lang.annotation.ElementType;
public class text1 {
public static void main(String[]args){
    Class c1=Object.class;//类
    Class c2= Comparable.class;//接口
    Class c3=String.class;//一维数组
    Class c4=int[][].class;//二维数组
    Class c5=Override.class;//注解
    Class c6= ElementType.class;//枚举
    Class c7=Integer.class;//基本数据类型
    Class c8=void.class;//void
    Class c9=Class.class;//class
    System.out.println(c1);
    System.out.println(c2);
    System.out.println(c3);
    System.out.println(c4);
    System.out.println(c5);
    System.out.println(c6);
    System.out.println(c7);
    System.out.println(c8);
    System.out.println(c9);
    //对于数组,只要元素类型和维度相同,那么就是同一个class
    int[] a=new int[10];
    int[] b=new int[100];
    System.out.println(a.getClass().hashCode());
    System.out.println(b.getClass().hashCode());
}
}

输出:

class java.lang.Object
class Collections.Comparable
class java.lang.String
class [[I
interface java.lang.Override
class java.lang.annotation.ElementType
class java.lang.Integer
void
class java.lang.Class
363771819
363771819

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

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

相关文章

【AI with ML】第 4 章 :使用公共数据集和TensorFlow 数据集

🔎大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎 📝个人主页-Sonhhxg_柒的博客_CSDN博客 📃 🎁欢迎各位→点赞…

Web前端105天-day43-JSCORE

JSCORE03 目录 前言 一、复习 二、块级作用域 三、声明提升 四、模板字符串 五、箭头函数 六、箭头函数的this 七、数组高阶函数 7.1.every 7.2.some 7.3.filter 7.4.map 7.5.join 八、ajax 九、作业 总结 前言 JSCORE学习开始 一、复习 函数的触发方式 call: 临…

跑步用头戴式耳机好吗、五款最适合跑步用的耳机推荐

无论您是为即将举行的运动进行训练的经验丰富的运动员,还是喜欢慢跑的人,一副好的运动型耳机都可以让您的日常锻炼变得与众不同。我们测试过市面上220多种蓝牙耳机,以下是我们针对跑步和锻炼的最佳耳机选择建议: 1、南卡Runner P…

[附源码]Nodejs计算机毕业设计基于web的学生社团管理系统Express(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置: Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术: Express框架 Node.js Vue 等等组成,B/S模式 Vscode管理前后端分…

springboot 创建第一个项目

创建springboot项目的方式有很多&#xff0c;一般通过IDEA直接创建。 参考&#xff1a;创建SpringBoot项目的四种方式 - Linqylin - 博客园 代码结构&#xff1a; 代码示例&#xff1a; 创建项目的时候导入了web依赖。 pom.xml&#xff1a; <?xml version"1.0&qu…

Marvell交换机芯片SMI接口读写协议

Marvell的88E6XXX系列交换机芯片基本都提供SMI&#xff08;Serial Management Interface&#xff09;接口。 SMI接口使用2线串行通信&#xff0c;一个MDC提供时钟&#xff0c;一个MDIO为双向数据引脚。 外部CPU通过这2个引脚访问芯片内部的寄存器。 SMI接口的通信时序如图所示&…

【Python】Gamma分布详解

文章目录初步介绍形状特征初步介绍 在学习Gamma分布之前&#xff0c;有必要复习一下Poisson分布&#xff1a;泊松分布 Poisson分布指的是&#xff0c;单个事件在某一刻发生的概率。Gamma分布更进一步&#xff0c;指的是某个事件在某个时刻发生第nnn次的概率。 p(x)xk−1e−λ…

PowerDesigner 模型类型介绍

目录 PowerDesigner 提供了两种方式组织模型 分别是Categories和Model types 1.Categories方式是从企业架构建模角度出发&#xff0c;主要包含业务层&#xff0c;信息层&#xff0c;应用层&#xff0c;技术层&#xff0c;需求与规划层 1.1 业务层主要用于业务流程&#xff0c…

python游戏开发的库你知道几个?

对这方面有兴趣的朋友可以去学习学习。 01 PyGame 官网&#xff1a; Pygame Front Page — pygame v2.1.4 documentation 概述&#xff1a; Pygame 是一组专为编写视频游戏而设计的 Python 模块。 它在优秀的 SDL 库之上添加了功能。这允许您使用 python 语言创建功能齐全…

MyBatisPlus框架:一文带你清晰整个MP框架逻辑

MyBatisPlus框架&#xff1a;一文带你清晰整个MP框架逻辑需求&#xff1a;如果搭建一个SpringBootMP的基本框架&#xff1f;并入门其API使用MP入门简介工程环境搭建数据库配置依赖Yaml框架流程简单介绍下MP的底层运行过程常用APIMP日志配置主键生成策略自动填充处理扩展插件MP乐…

allegro中添加logo (方法二)

allegro中添加logo &#xff08;方法二&#xff09;1、 先制作好bmp格式的文件2、 Allegro中新建一个format symbol文件3、 导入IPF文件4、 方法对比软件环境&#xff1a;cadence 16.6前言&#xff1a;很多时候我们在设计pcb的时候都会在pcb上添加自己产品的logo&#xff0c;现…

Python《字符,符号,函数,索引》

函数描述len()计算序列的长度max()找出序列中的最大元素min()找出序列中的最小元素list()将序列转换为列表str()将序列转换为字符串sum()计算元素的和sorted()对元素进行排序enumerate()将序列组合为一个索引序列&#xff0c;多用在 for 循环中 关键字 andexecnotassertfinall…

Linux网络编程(二)——socket通信基础

目录 一、socket 二、字节序 &#xff08;一&#xff09;字节序转换函数 三、Socket地址 &#xff08;一&#xff09;通用socket地址 &#xff08;二&#xff09;专用socket地址 四、IP地址转换 五、TCP通信流程 &#xff08;一&#xff09;TCP和UDP的区别 &#xff…

深入浅出RPC

什么是RPC 为什么要有RPC PRC架构组件 RPC框架需要解决的问题&#xff1f; 1、如何确定客户端和服务端之间的通信协议&#xff1f; 2、如何更高效地进行网络通信&#xff1f; 3、服务端提供的服务如何暴露给客户端&#xff1f; 4、客户端如何发现这些暴露的服务&#xff1f; 5…

云存储学习笔记--3

目录前言1. 原理2. 实验前言 那么&#xff0c;根据我们上一版块的解释&#xff0c;其实经过思考会发现&#xff0c;传统的分区格式化会有一些问题&#xff0c;比如说&#xff1a;当我数据的存储大小超过了所有单个磁盘的存储空间大小的时候&#xff0c;会发现即使剩余空间总和…

论文复现-1论文重读:Black-Box Tuning for Language-Model-as-a-Service

论文核心&#xff1a;使用PLM的API进而完成prompt learning&#xff0c;微调完成任务。 具体来说&#xff0c;是采用连续prompts拼接在input_text之后&#xff0c;然后&#xff0c;通过derivative-free的框架&#xff0c;完成任务。 一、背景&#xff08;Introduction&#x…

门店数字化管理|门店督导工作监管难?SpaceSight 来帮忙

在门店管理中&#xff0c;这些问题是否一直困扰着你&#xff1a; 哪家店员工作更细致高效&#xff1f;难评估&#xff01; 有哪些门店问题高频发生&#xff1f;难发现&#xff01; 不同门店运营差距有多大&#xff1f;难界定&#xff01; SpaceSight 系列第二篇&#xff0c;为…

看看阿里程序员是怎样讲限流的

限流算法很多,常见的有三类,分别是计数器算法、漏桶算法、令牌桶算法,下面逐一讲解。 计数器算法 简单粗暴,比如指定线程池大小&#xff0c;指定数据库连接池大小、nginx连接数等,这都属于计数器算法。 计数器算法是限流算法里最简单也是最容易实现的一种算法。举个例子,比如…

YOLO系列目标检测算法——PP-YOLOv2

YOLO系列目标检测算法目录 - 文章链接 YOLO系列目标检测算法总结对比- 文章链接 YOLOv1- 文章链接 YOLOv2- 文章链接 YOLOv3- 文章链接 YOLOv4- 文章链接 Scaled-YOLOv4- 文章链接 YOLOv5- 文章链接 YOLOv6- 文章链接 YOLOv7- 文章链接 PP-YOLO- 文章链接 …

>python可视化神器altair

python可视化神器一.些简单图形的绘制(一).柱状图1. 然后我们还可以设置高亮柱状图的某一根柱子&#xff0c;其他柱子设置为一样的颜色&#xff1a;2. 翻转图片&#xff0c;同时添加图片标注&#xff0c;在图上加上数据3.在图形上添加线条4. 组合图&#xff0c;柱状图折线图(二…