【数据结构】反射、枚举

⭐ 作者:小胡_不糊涂
🌱 作者主页:小胡_不糊涂的个人主页
📀 收录专栏:浅谈数据结构
💖 持续更文,关注博主少走弯路,谢谢大家支持 💖

反射、枚举

  • 1. 反射
    • 1.1 定义
    • 1.2 反射相关的类
    • 1.3 反射示例
      • 1.3.1 获得Class对象的三种方式
    • 1.3 反射优点和缺点
  • 2. 枚举
    • 2.1 定义
    • 2.2 使用

在这里插入图片描述

1. 反射

1.1 定义

Java的反射(reflection)机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到,那么,我们就可以修改部分类型信息;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射(reflection)机制

Java程序中许多对象在运行时会出现两种类型:运行时类型(RTTI)编译时类型,例如Person p = newStudent();这句代码中p在编译时类型为Person,运行时类型为Student。程序需要在运行时发现对象和类的真实信息。而通过使用反射程序就能判断出该对象和类属于哪些类。

1.2 反射相关的类

类名用途
Class类代表类的实体,在运行的Java应用程序中表示类和接口
Field类代表类的成员变量/类的属性
Method类代表类的方法
Constructor类代表类的构造方法

Class类中的相关方法:

  1. 常用获得类相关的方法
方法用途
getClassLoader()获得类的加载器
getDeclaredClasses()返回一个数组,数组中包含该类中所有类和接口类的对象(包括私有的)
forName(String className)根据类名返回类的对象
newInstance()创建类的实例
getName()获得类的完整路径名字
  1. 常用获得类中属性相关的方法(以下方法返回值为Field相关)
方法用途
getField(String name)获得某个公有的属性对象
getFields()获得所有公有的属性对象
getDeclaredField(String name)获得某个属性对象
getDeclaredFields()获得所有属性对象
  1. 获得类中构造器相关的方法(以下方法返回值为Constructor相关)
方法用途
getConstructor(Class…<?> parameterTypes)获得该类中与参数类型匹配的公有构造方法
getConstructors()获得该类的所有公有构造方法
getDeclaredConstructor(Class…<?> parameterTypes)获得该类中与参数类型匹配的构造方法
getDeclaredConstructors()获得该类所有构造方法
  1. 获得类中方法相关的方法(以下方法返回值为Method相关)
方法用途
getMethod(String name, Class…<?> parameterTypes)获得该类某个公有的方法
getMethods()获得该类所有公有的方法
getDeclaredMethod(String name, Class…<?> parameterTypes)获得该类某个方法
getDeclaredMethods()获得该类所有方法

1.3 反射示例

1.3.1 获得Class对象的三种方式

在反射之前,我们需要做的第一步就是先拿到当前需要反射的类的Class对象,然后通过Class对象的核心方法,达到反射的目的,即:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到那么,我们就可以修改部分类型信息。

  1. 使用 Class.forName(“类的全路径名”); 静态方法。前提:已明确类的全路径名
  2. 使用 .class 方法。仅适合在编译前就已经明确要操作的 Class
  3. 使用类对象的 getClass()方法

示例:三种方式的使用方法
创建Student类:

class Student{
    //私有属性name
    private String name = "hu";
    //公有属性age
    public int age = 18;
    //不带参数的构造方法
    public Student(){
        System.out.println("Student()");
    }
    private Student(String name,int age) {
        this.name = name;
        this.age = age;
        System.out.println("Student(String,name)");
    }
    private void eat(){
        System.out.println("i am eat");
    }
    public void sleep(){
        System.out.println("i am sleep");
    }
    private void function(String str) {
        System.out.println(str);
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

三种方式的实现:

public class TestDemo {
    public static void main(String[] args) {
        //1.通过getClass获取Class对象
        Student s1 = new Student();
        Class c1 = s1.getClass();

        //2.直接通过 类名.class 的方式得到,该方法最为安全可靠,程序性能更高
        //这说明任何一个类都有一个隐含的静态成员变量 class
        Class c2 = Student.class;

        //3.通过 Class 对象的 forName() 静态方法来获取,用的最多,
        //但可能抛出 ClassNotFoundException 异常
        Class c3 = null;
        try {
        //注意这里是类的全路径,如果有包需要加包的路径
            c3 = Class.forName("Student");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println(c1.equals(c2));
        System.out.println(c1.equals(c3));
        System.out.println(c2.equals(c3));
        //一个类在 JVM 中只会有一个 Class 实例,即我们对上面获取的
        //c1,c2,c3进行 equals 比较,发现都是true
    }
}

1.3 反射优点和缺点

优点:

  1. 对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法。
  2. 增加程序的灵活性和扩展性,降低耦合性,提高自适应能力。
    缺点:
  3. 使用反射会有效率问题。会导致程序效率降低。
  4. 反射技术绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂。

2. 枚举

2.1 定义

枚举是在JDK1.5以后引入的。主要用途是:将一组常量组织起来,在这之前表示一组常量通常使用定义常量的方式:

public static final int RED = 1;
public static final int GREEN = 2;
public static final int BLACK = 3;

但是常量举例有不好的地方,例如:可能碰巧有个数字1,但是他有可能误会为是RED,现在我们可以直接用枚举来进行组织,这样一来,就拥有了类型,枚举类型。而不是普通的整形1。

public enum TestEnum {
	RED,BLACK,GREEN;
}

优点:将常量组织起来统一进行管理
场景:错误状态码,消息类型,颜色的划分,状态机等等…

**本质:**是 java.lang.Enum 的子类,也就是说,自己写的枚举类,就算没有显示的继承 Enum ,但是其默认继承了这个类。

2.2 使用

  1. switch 语句
public enum TestEnum {
    RED,BLACK,GREEN,WHITE;
    public static void main(String[] args) {
        TestEnum testEnum2 = TestEnum.BLACK;
        switch (testEnum2) {
            case RED:
                System.out.println("red");
                break;
            case BLACK:
                System.out.println("black");
                break;
            case WHITE:
                System.out.println("WHITE");
                break;
            case GREEN:
                System.out.println("black");
                break;
            default:
                break;
        }
    }
}
//输出:black
  1. 常用方法
方法名称描述
values()以数组形式返回枚举类型的所有成员
ordinal()获取枚举成员的索引位置
valueOf()将普通字符串转换为枚举实例
compareTo()比较两个枚举成员在定义时的顺序

上述方法的实现:
示例一:

public enum TestEnum {
    RED, BLACK, GREEN, WHITE;
    public static void main(String[] args) {
        TestEnum[] testEnum2 = TestEnum.values();
        for (int i = 0; i < testEnum2.length; i++) {
            System.out.println(testEnum2[i] + " " + testEnum2[i].ordinal());
        }
        System.out.println("=========================");
        System.out.println(TestEnum.valueOf("GREEN"));
    }
}

运行结果:
在这里插入图片描述
示例二:

public enum TestEnum {
	RED,BLACK,GREEN,WHITE;
	public static void main(String[] args) {
		//拿到枚举实例BLACK
		TestEnum testEnum = TestEnum.BLACK;
		//拿到枚举实例RED
		TestEnum testEnum21 = TestEnum.RED;
		System.out.println(testEnum.compareTo(testEnum21));//1
		System.out.println(BLACK.compareTo(RED));//1
		System.out.println(RED.compareTo(WHITE));//-3
	}
}

在Java当中枚举实际上就是一个类。所以我们在定义枚举的时候,还可以这样定义和使用枚举:

public enum TestEnum {
    RED("red",1),BLACK("black",2),WHITE("white",3),GREEN("green",4);
    private String name;
    private int key;
    /**
     * 1、当枚举对象有参数后,需要提供相应的构造函数
     * 2、枚举的构造函数默认是私有的
     * @param name
     * @param key
     */
    private TestEnum (String name,int key) {
        this.name = name;
        this.key = key;
    }
    public static TestEnum getEnumKey (int key) {
        for (TestEnum t: TestEnum.values()) {
            if(t.key == key) {
                return t;
            }
        }
        return null;
    }
    public static void main(String[] args) {
        System.out.println(getEnumKey(2));//BLACK
    }
}

枚举的构造方法默认是私有的
任何一个类,哪怕其构造方法是私有的,我们也可以通过反射拿到他的实例对象,枚举的构造方法虽然也是私有的,但是不能通过反射获取枚举类的实例

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Java0基础学Java第八颗】 -- 继承与多态 -- 继承

8.继承与多态 8.1 继承8.1.1 为什么需要继承8.1.2 继承概念8.1.3 继承的语法8.1.4 super关键字8.1.5 父类成员访问子类中访问父类的成员变量子类中访问父类的成员方法 8.1.6 子类构造方法8.1.7 super和this8.1.8 再谈初始化8.1.9 protected 关键字同一包中同一类同一包中不同的…

Linux Vim批量注释和自定义注释

使用 Vim 编辑 Shell 脚本&#xff0c;在进行调试时&#xff0c;需要进行多行的注释&#xff0c;每次都要先切换到输入模式&#xff0c;在行首输入注释符"#"再退回命令模式&#xff0c;非常麻烦。连续行的注释其实可以用替换命令来完成。 换句话说&#xff0c;在指定…

NFS服务器的搭建

架设一台NFS服务器&#xff0c;并按照以下要求配置 准备阶段&#xff1a;准备两台虚拟机&#xff0c;一台作为服务端&#xff0c;一台作为客户端 服务端&#xff08;Server&#xff09;&#xff1a;192.168.75.139 客户端&#xff08;Client&#xff09;:192.168.75.160 两…

Python tkinter实现复刻Windows记事本UI和菜单的文本编辑器(二)

上一篇&#xff1a;Python tkinter实现复刻Windows记事本UI和菜单的文本编辑器&#xff08;一&#xff09;-CSDN博客 下一篇&#xff1a;敬请耐心等待&#xff0c;如发现BUG以及建议&#xff0c;请在评论区发表&#xff0c;谢谢&#xff01; 相对上一篇文章&#xff0c;本片文…

算术运算符、自增自减运算符、赋值运算符、关系运算符、逻辑运算符、三元运算符

1.算术运算符 public class OperatorDemo1 {public static void main(String[] args) {int a 10;int b 2;System.out.println(a b);System.out.println(a - b);System.out.println(a * b);System.out.println(a / b);System.out.println(5 / 2);System.out.println(5.0 / 2);…

vue3 + antd 图片上传 (精简篇)cv即可

使用antd组件库里的 a-upload 上传图片 template代码&#xff1a; <a-upload name"idCardzm" list-type"picture-card" class"avatar-uploader" :show-upload-list"false":before-upload"beforeUpload" :customRequest…

LINUX入门篇【5】----程序的翻译过程解析

前言&#xff1a; 在C语言阶段我们已经讲过程序的翻译过程&#xff0c;我们知道程序是由预处理&#xff0c;编译&#xff0c;汇编&#xff0c;链接四部分组成的&#xff0c;但是&#xff0c;当时受到C语言编译器的限制&#xff0c;我们没法去深刻体会这个过程&#xff0c;所以…

软件研发团队适用的项目管理工具推荐

Zoho Projects是一款专为大型产研团队设计的项目管理工具&#xff0c;它也是许多软件开发行业高速成长背后的生产线。与其他项目管理产品相比&#xff0c;Zoho Projects最大的不同之处在于其独特的流程设计。在软件上线初期&#xff0c;Zoho Projects能够有效地帮助软件研发公司…

mac使用VMware Fusion安装Centos 7系统

mac主机芯片&#xff1a;Apple M2 Pro VMware-Fusion&#xff1a;13.5 centos&#xff1a;7 第一次操作&#xff1a; 按步骤选择操作系统 在选择虚拟启动虚拟机没有安装centos的界面 而是下图 改动&#xff1a;把UEFI换成BIOS ——>无果 第二次操作&#xff1a; 直接…

数据仓库工具箱-第三章-零售业务

文章目录 一、维度模型设计的4步过程1.1 第一步&#xff1a;选择业务过程1.2 第二步&#xff1a;声明粒度1.3 第三步&#xff1a;确定维度1.4 第四步&#xff1a;确定事实 二、零售业务案例研究2.1 第一步&#xff1a;选择业务过程2.2 第二步&#xff1a;声明粒度2.3 第三步&am…

5.浮点数及其运算

目录 一. 浮点数的表示 &#xff08;1&#xff09;表示 &#xff08;2&#xff09;规格化 二. IEEE 754标准 三. 浮点数的运算 &#xff08;1&#xff09;步骤 &#xff08;2&#xff09;关于舍入 四. C语言的强制类型转换 一. 浮点数的表示 &#xff08;1&#xff09…

原型模式(创建型)

一、前言 原型模式是一种创建型设计模式&#xff0c;它允许在运行时通过克隆现有对象来创建新对象&#xff0c;而不是通过常规的构造函数创建。在原型模式中&#xff0c;一个原型对象可以克隆自身来创建新的对象&#xff0c;这个过程可以通过深度克隆或浅克隆来实现。简单说原型…

MySQL中UUID主键的优化

UUID&#xff08;Universally Unique IDentifier 通用唯一标识符&#xff09;&#xff0c;是一种常用的唯一标识符&#xff0c;在MySQL中&#xff0c;可以利用函数uuid()来生产UUID。因为UUID可以唯一标识记录&#xff0c;因此有些场景可能会用来作为表的主键&#xff0c;但直接…

AIX5.3安装weblogic10.3

目录 1安装IBM JDK 1.6 2图形化准备 3安装weblogic 准备 4图形化界面安装 1安装IBM JDK 1.6 1.1检查操作系统 # oslevel 5.3.0.0 # bootinfo -y (显示AIX机器硬件是64位) 64 # bootinfo -K (显示AIX系统内核是64位) 64 因此&#xff0c;系统需要安装64位的jdk&#xff0c;…

使用非递归的方式实现归并排序

使用非递归的方式实现归并排序 话不多说&#xff0c;直接上代码&#xff1a; public class MergySort {public static void main(String[] args) {int[] nums {38, 27, 43, 3, 9, 82, 10};int[] sortedArray MergySort.mergySort(nums);// 输出排序后的数组for (int num : …

AIGC:使用bert_vits2实现栩栩如生的个性化语音克隆

1 VITS2模型 1.1 摘要 单阶段文本到语音模型最近被积极研究&#xff0c;其结果优于两阶段管道系统。以往的单阶段模型虽然取得了较大的进展&#xff0c;但在间歇性非自然性、计算效率、对音素转换依赖性强等方面仍有改进的空间。本文提出VITS2&#xff0c;一种单阶段的文本到…

如何构建并提高自己的核心竞争力?

上一篇文章聊到了软件工程师的核心竞争力主要分为三个方面&#xff1a;快速学习能力、解决问题能力和个人影响力&#xff0c;且核心竞争力的培养和提高需要长时间实践和积累&#xff0c;并不是短时间就可以达到的。这篇文章&#xff0c; 来聊聊如何培养和提高自己的核心竞争力。…

里氏代换原则

package com.jmj.principles.dmeo2.after;/*** 四边形接口*/ public interface Quadrilateral {double getLength();double getWidth();}package com.jmj.principles.dmeo2.after;/*** 长方形类*/ public class Rectangle implements Quadrilateral{private double length;priv…

windowCPU虚拟化已禁用解决方案

windowCPU虚拟化已禁用解决方案 1. 前言 window电脑要安装Docker或者VMware虚拟机就需要开启windows自身的虚拟化功能&#xff0c;除了在设置上要开启Hyper-V只要还需要开启CPU的虚拟化功能&#xff0c;而CPU的虚拟化则需要通过进入BIOS设置中开启 2. 检查是否开启了虚拟化功…

探索Linux世界:从基础到高级

标题 探索Linux世界&#xff1a;从基础到高级 &#x1f680;第一章&#xff1a;Linux入门篇第二章&#xff1a;掌握Linux基础命令第三章&#xff1a;文件操作的艺术第四章&#xff1a;征服vi/vim编辑器第五章&#xff1a;掌握Linux全部命令 文末赠书 博主 默语带您 Go to New W…