在枚举里面定义方法以及原理

本文探讨了如何在枚举中定义方法来替代if-else结构,介绍了两种实现方式:使用抽象方法和Java 8的函数接口,并分析了这种方法的适用场景。同时,文章提醒虽然这种方式在某些特定情况下有用,但通常不推荐,因为枚举的主要作用是保存常量。枚举能定义方法的原因在于每个枚举值都是枚举类的实例,可以通过构造方法实现方法或利用Java 8的Lambda表达式传入函数对象。

有些场景下,根据某个key值 去决定调用哪个方法, 除了if else之外
定义在枚举里面也是一种方式 ,比 if else 好用

有两种实现,一种是抽象方法 ,如下

package com.souche.sfs.server;

import java.util.function.Function;

public enum MethodEnum {

//定义方法1  以及其对应的code  ,然后实现其抽象方法
    Method1(1) {
        @Override
        void run() {
            System.out.println("第一个方法");
        }
    },

//定义方法2 以及其对应的code 然后实现其抽象方法
    Method2(2) {
        @Override
        void run() {
            System.out.println("第二个方法");
        }
    };
    
//寻找符合的code来执行其方法
   static public void runMethod(Integer code) {
        for (MethodEnum methodEnum : MethodEnum.values()) {
            if (methodEnum.getCode().equals(code)) {
                methodEnum.run();
            }
        }
    }


    public Integer getCode() {
        return code;
    }


    MethodEnum(Integer code) {
        this.code = code;
    }

//定义枚举的code
    private Integer code;

//枚举的code对应的方法 定义成抽象的  然后在定义枚举值的时候实现
    abstract void run();

}


运行结果


    public static void main(String[] args) {
    //指定枚举值调用
        MethodEnum.Method1.run();
        MethodEnum.Method2.run();
        // 根据code调用
        MethodEnum.runMethod(2);
    }

执行结果
在这里插入图片描述

二是使用java8的函数接口

public enum MethodEnum {


// 使用lamada表达式的形式 传入一个(参数)->{表达式 返回值} 的函数
 
    Method1(1,(In)->{System.out.println("第1个方法,参数为"+In); return 1;}),

    Method2(2,(In)->{System.out.println("第2个方法,参数为"+In); return 1;});

    public Integer getCode() {
        return code;
    }

    public Function getFunction() {
        return function;
    }



    private Integer code;
    //定义Function为类变量
   private Function function;

//Function<返回值类型, 参数类型>    
    MethodEnum(Integer code, Function<Integer, Integer> function) {
        this.code = code;
        this.function=function;
    }
}

执行

   public static void main(String[] args) {
        MethodEnum.Method1.getFunction().apply(1);
        MethodEnum.Method2.getFunction().apply(2);
    }

结果
在这里插入图片描述

以上写法在某些特定的场景下可以简化if else ,正常情况下不太建议使用,因为还是让枚举去做枚举该做的事情吧,比如说保存常量。

原理:
那么为什么可以定义方法?

枚举里面的每一个值,实际上都是该枚举的一个实例对象,
枚举的构造方法是使用创建该枚举的枚举值的。

在枚举里面定义抽象方法,在定义枚举值的时候实现它。
或者在枚举的构造参数里面传入function对象,在java8的lamda表达式中这个代表一个函数

<think> 我们需要将之前的表结构定义在头文件(.h)中,以便多个源文件可以共享。 具体步骤: 1. 在头文件中定义枚举和结构体。 2. 声明全局二维数组(但注意在头文件中定义全局变量会导致重复定义问题,所以通常用extern声明,在.c文件中定义)。 3. 提供初始化函数和访问函数的声明(在头文件中声明,在.c文件中实现)。 因此,我们将代码拆分为: - 头文件(.h):包含类型定义、函数声明和全局数组的extern声明。 - 源文件(.c):包含全局数组的定义、初始化函数和访问函数的实现。 注意:为了防止头文件重复包含,需要使用头文件保护(#ifndef ... #define ... #endif)。 以下是具体代码示例: 头文件(scenario_table.h)内容: </think> ### 在头文件(.h)中定义静态配置表的方法 在头文件中定义场景类型、数据流类型和配置表是完全可行的,但需要正确处理**全局可见性**和**初始化**问题。以下是优化的头文件实现方案: #### 头文件代码(`scenario_config.h`) ```c #ifndef SCENARIO_CONFIG_H #define SCENARIO_CONFIG_H #include <stdint.h> // 1. 定义数据流类型枚举(添加数量统计项) typedef enum { CAM_SCENARIO_FE_3A_OUTPUT = 0, CAM_SCENARIO_FE_RAW10_OUTPUT, CAM_SCENARIO_LITE_YUV_OUTPUT, CAM_SCENARIO_GDC_MAP_TABLE, NUM_CAM_SCENARIO_BUF_TYPE // 枚举元素数量统计 } cam_scenario_buf_type; // 2. 定义场景类型枚举 typedef enum { SCENARIO_A = 0, SCENARIO_B, SCENARIO_C, NUM_SCENARIOS // 场景类型数量统计 } scenario_type; // 3. 定义缓冲区信息结构体 typedef struct { uint32_t buf_num; uint32_t input_width; uint32_t input_height; } cam_scenario_buffer_info; // 4. 声明配置表为extern(在.c文件中定义) extern const cam_scenario_buffer_info BUFFER_CONFIG_TABLE[NUM_SCENARIOS][NUM_CAM_SCENARIO_BUF_TYPE]; // 5. 声明访问函数 const cam_scenario_buffer_info* get_buffer_config(scenario_type scenario, cam_scenario_buf_type buf_type); #endif // SCENARIO_CONFIG_H ``` #### 源文件实现(`scenario_config.c`) ```c #include "scenario_config.h" // 1. 定义并初始化配置表(static const确保只读性) const cam_scenario_buffer_info BUFFER_CONFIG_TABLE[NUM_SCENARIOS][NUM_CAM_SCENARIO_BUF_TYPE] = { // SCENARIO_A 配置 [SCENARIO_A] = { [CAM_SCENARIO_FE_3A_OUTPUT] = { .buf_num = 2, .input_width = 1920, .input_height = 1080 }, [CAM_SCENARIO_FE_RAW10_OUTPUT] = { .buf_num = 4, .input_width = 1280, .input_height = 720 }, [CAM_SCENARIO_LITE_YUV_OUTPUT] = { .buf_num = 1, .input_width = 800, .input_height = 600 }, [CAM_SCENARIO_GDC_MAP_TABLE] = { .buf_num = 3, .input_width = 640, .input_height = 480 } }, // SCENARIO_B 配置 [SCENARIO_B] = { [CAM_SCENARIO_FE_3A_OUTPUT] = { .buf_num = 3, .input_width = 2048, .input_height = 1536 }, [CAM_SCENARIO_FE_RAW10_OUTPUT] = { .buf_num = 5, .input_width = 1600, .input_height = 900 } // 其他数据流使用默认值 }, // SCENARIO_C 配置 [SCENARIO_C] = { [CAM_SCENARIO_GDC_MAP_TABLE] = { .buf_num = 6, .input_width = 3840, .input_height = 2160 } } }; // 2. 访问函数实现(返回指针避免数据拷贝) const cam_scenario_buffer_info* get_buffer_config(scenario_type scenario, cam_scenario_buf_type buf_type) { if (scenario >= NUM_SCENARIOS || buf_type >= NUM_CAM_SCENARIO_BUF_TYPE) { return NULL; // 无效参数返回空指针 } return &BUFFER_CONFIG_TABLE[scenario][buf_type]; } ``` ### 关键设计解析 #### 1. 头文件保护机制 ```c #ifndef SCENARIO_CONFIG_H #define SCENARIO_CONFIG_H // ... 内容 ... #endif ``` **作用**:防止头文件被多次包含导致的重复定义错误 #### 2. 类型定义优化 - 使用 `typedef` 创建新类型名,简化后续使用 - 枚举添加 `NUM_XXX` 项,自动计算元素数量 - 使用 `stdint.h` 的 `uint32_t` 确保跨平台一致性 #### 3. 配置表声明技巧 ```c extern const cam_scenario_buffer_info BUFFER_CONFIG_TABLE[][]; ``` **原理**: - `extern` 声明全局变量在头文件中 - 实际定义在 `.c` 文件中,避免多重定义错误 - `const` 确保配置表只读,保护数据安全 #### 4. 初始化语法优势 ```c [SCENARIO_A] = { [CAM_SCENARIO_FE_3A_OUTPUT] = { ... } } ``` **好处**: - 指定初始化器 (Designated Initializers) - 明确索引对应关系,提高可读性 - 支持乱序初始化,未指定项自动清零 #### 5. 访问函数设计 ```c const cam_scenario_buffer_info* get_buffer_config(...); ``` **优化点**: - 返回 `const` 指针而非结构体副本 - 避免数据拷贝开销(尤其大结构体) - 空指针返回值提供错误处理机制 ### 使用示例 ```c #include "scenario_config.h" #include <stdio.h> int main() { // 获取场景A的FE_3A_OUTPUT配置 const cam_scenario_buffer_info *info = get_buffer_config(SCENARIO_A, CAM_SCENARIO_FE_3A_OUTPUT); if (info) { printf("Buffer配置: num=%u, %ux%u\n", info->buf_num, info->input_width, info->input_height); } else { printf("无效场景或数据流类型!\n"); } return 0; } ``` ### 方案优势 1. **类型安全**:强类型枚举防止错误值传递 2. **内存高效**:常量表存储在只读数据段(编译期初始化) 3. **访问快速**:O(1)时间复杂度直接索引访问 4. **扩展灵活**:新增场景/数据流只需更新枚举和配置表 5. **跨文件共享**:通过头文件暴露接口,隐藏实现细节
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值