0
点赞
收藏
分享

微信扫一扫

Windows图形界面(GUI)-MFC-C/C++ - MFC菜单

简单聊育儿 2024-07-29 阅读 26

文章目录

目录

 

前言

一、枚举

1.1 枚举的概念

​编辑 

1.2 枚举的特点

1.3 枚举的实际运用

1. 状态机,描述属性的多种状态

2.  策略模式,让客户端动态切换不同的策略

 3. 数据字典,定义一组错误代码展示对应的错误消息

4. 迭代器模式,枚举类型的循环使用

二、注解

2.1 注解的概念

2.注解的特点

2.1 格式:

2.2 注解的分类

1. 内置注解:

2. 自定义注解:

2.3 用途

2.4 使用反射获得是否被指定注解修饰

1. 判断类是否被注解修饰

 2. 判断方法是否被注解修饰

2.5 模拟tomcat输入对应的路径执行对应的方法 

1. 自定义@Controller注解

2. 自定义@RequestMapping注解

 3. 自定两个控制器

 4. 模拟tomcat

总结



前言

        枚举和注解都是 Java 中重要的语言特性,枚举用于定义常量集合和类型安全,而注解是元数据的一种形式,可以在代码中添加元数据信息,用来提供给编译器和其他工具进行特定的处理。通过合理使用枚举和注解,可以提高代码的可读性、灵活性和功能性。注解就一句核心:注解是给程序看的注释,注解离开了反射什么也不是。


一、枚举

枚举是一种特殊的数据类型,用于定义一组命名的常量集合。

1.1 枚举的概念

1. 类被public final修饰,默认继承Enum类,因此不能被继承也不可继承。

2. 成员变量默认被public static final enum修饰,并且多个成员之间用逗号隔开,会按照声明顺序按照0开始分配序号。name值为变量名。CompareTo默认根据序号比较。

3. 默认:直接打印返回的是变量名。因为底层toString()方法默认返回name

 

1.2 枚举的特点

  1. 声明常量集合:枚举允许开发者定义一组具名的常量,这些常量在整个程序中可以被安全地引用。

  2. 类型安全:枚举提供了类型安全性,编译器会检查枚举常量的使用,避免使用错误的常量值。

  3. 增强代码可读性:通过枚举,可以使用具有语义的名称来表示常量,提高代码的可读性和可维护性。

  4. 支持方法和属性:枚举不仅可以包含常量,还可以定义方法和属性,使得枚举可以拥有更复杂的行为。

  5. switch 语句的支持:Java 的枚举可以很方便地与 switch 语句结合使用,提高代码的简洁性和可读性。

1.3 枚举的实际运用

1. 状态机,描述属性的多种状态

标记一个商品表中的订单属性的状态,其中含有枚举常量,新订单、处理中、完成、取消

package enum_demo1;

/**
 * @author windStop
 * @version 1.0
 * @description 枚举作用一:状态机
 * @date 2024年07月26日16:05:43
 */
//枚举订单状态
enum OrderStatus {
    NEW,        // 新订单
    PROCESSING, // 处理中
    COMPLETED,  // 完成
    CANCELED;   // 取消
}
//订单JavaBean
class Order {
    private OrderStatus status;

    public OrderStatus getStatus() {
        return status;
    }

    public void setStatus(OrderStatus status) {
        this.status = status;
    }
}
public class FiniteStateMachine {
    public static void main(String[] args) {
        Order order = new Order();
        //1. 获取订单状态
        OrderStatus currentStatus = order.getStatus();
        //2. 设置订单状态
        order.setStatus(OrderStatus.NEW); // 设置为新订单状态
        order.setStatus(OrderStatus.PROCESSING); // 设置为处理中状态
        order.setStatus(OrderStatus.COMPLETED); // 设置为完成状态
        order.setStatus(OrderStatus.CANCELED); // 设置为取消状态
        //3. 使用订单状态
        if (order.getStatus() == OrderStatus.NEW) {
            // 处理新订单的逻辑
        } else if (order.getStatus() == OrderStatus.PROCESSING) {
            // 处理处理中的订单逻辑
        } else if (order.getStatus() == OrderStatus.COMPLETED) {
            // 处理完成的订单逻辑
        } else if (order.getStatus() == OrderStatus.CANCELED) {
            // 处理取消的订单逻辑
        }

    }
}

2.  策略模式,让客户端动态切换不同的策略

策略模式(Strategy Pattern)是一种行为设计模式,它允许定义一系列算法,并将每种算法封装到具有共同接口的独立类中,使它们可以互相替换。策略模式使得算法可以独立于客户端而变化,从而使得客户端可以根据需要在运行时选择算法

模拟用户选择的按钮选择对应的支付方式。 

package enum_demo2;
/**
 * @author windStop
 * @version 1.0
 * @description 枚举作用二:策略模式
 * @date 2024年07月26日16:06:26
 */
public enum PaymentMethod {
    CREDIT_CARD {
        @Override
        public void pay(double amount) {
            // 实现信用卡支付逻辑
        }
    },
    PAYPAL {
        @Override
        public void pay(double amount) {
            // 实现PayPal支付逻辑
        }
    },
    BANK_TRANSFER {
        @Override
        public void pay(double amount) {
            // 实现银行转账支付逻辑
        }
    };

    public abstract void pay(double amount);
}

 3. 数据字典,定义一组错误代码展示对应的错误消息

通过枚举类型 ErrorCode 来定义一组固定的错误代码和对应的错误消息,以提高代码的可读性和维护性,并用于统一管理常量值或数据字典。

package enum_demo3;

/**
 * @author windStop
 * @version 1.0
 * @description 枚举作用三:用枚举类来表示数据字典或常量值
 * @date 2024年07月26日16:11:07
 */
public enum ErrorCode {
    INVALID_INPUT(1001, "Invalid input"),
    NETWORK_ERROR(2001, "Network error"),
    DATABASE_ERROR(3001, "Database error");

    private final int code;
    private final String message;

    ErrorCode(int code, String message) {
        this.code = code;
        this.message = message;
    }

    public int getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }
}

4. 迭代器模式,枚举类型的循环使用

虽然这里称为迭代器模式,但更确切地说,它展示了枚举类型的循环使用。通过 getNextDay 方法,可以方便地获取当前一周中某一天的下一天,使得处理周期性任务或日期操作更加便捷和可读。 

package enum_demo4;
/**
 * @author windStop
 * @version 1.0
 * @description 枚举功能四:迭代器模式
 * @date 2024年07月26日16:14:24
 */
public enum Weekday {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;

    /**
     * getNextDay 是一个静态方法,用于获取当前给定 currentDay 的下一天是什么。
     * @param currentDay
     * @return
     * currentDay.ordinal() 返回 currentDay 枚举常量的序号(从 0 开始)。
     * values() 方法返回 Weekday 枚举类型的所有枚举常量的数组。
     * (currentDay.ordinal() + 1) % values().length 计算出当前 currentDay 的下一个枚举常量的序号。由于枚举是循环的,所以用取模运算确保循环。
     * values()[...] 使用计算得到的序号获取下一个枚举常量。
     */
    public static Weekday getNextDay(Weekday currentDay) {
        return values()[(currentDay.ordinal() + 1) % values().length];
    }
}

二、注解

2.1 注解的概念

2.注解的特点

2.1 格式:

public @interface MyAnno {
    String value();
    String name() default "匿名";
    int age() default 21;
}
  1. 看似属性很像一个 抽象类,可千万不要理解成抽象类。
  2. 这些成员变量用于定义注解的元素。编译器会在底层自动生成相关的接口和方法,以便在运行时获取注解的元数据。
  3. 注解的属性在注解的定义中以“无形参的抽象方法”形式来声明,其方法名定义了该属性的名字,其返回值定义了该属性的类型
  4. default 声明默认值。

2.2 注解的分类

1. 内置注解:
  • 元注解: 用于注解其他注解的注解,如 @Retention@Target@Documented 等。


     
  • 预定义注解: Java提供了一些内置的注解,如 @Override@Deprecated@SuppressWarnings 等,用于标记方法的重写、标记过时的方法或类、抑制编译器警告等。
  1. @Override:用于标识一个方法覆盖了父类中的方法。

  2. @Deprecated:用于标记已过时的方法、类或字段,表示不推荐使用,通常是因为有更好的替代方法。

  3. @SuppressWarnings:抑制编译器警告,可以用于方法、类、字段等,告诉编译器忽略特定的警告信息。

  4. @SafeVarargs:用于抑制 Java 编译器关于使用可变参数方法时的警告信息。

  5. @FunctionalInterface:用于指示接口类型是一个函数式接口,即只包含一个抽象方法的接口,可以用作 Lambda 表达式的类型。

  6. @Native:用于标记一个方法是本地方法,即通过 JNI(Java Native Interface)调用的方法。

  7. @Target:用于指定注解可以应用的地方,例如方法、类、字段等。

  8. @Retention:用于指定注解的保留策略,即注解在什么级别可用,如源码(SOURCE)、类文件(CLASS)、运行时(RUNTIME)。

  9. @Documented:用于指定注解是否包含在 JavaDoc 中。

2. 自定义注解:
  • 可以定义自己的注解,通过元注解指定注解的使用方式、目标和保留策略,定义注解的成员变量来传递注解的参数信息,并通过反射进行获取。

1.定义自定注解

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno {
    String value();
    String name() default "匿名";
    int age() default 21;
}

2. 定义javabean

public class Student {
    @MyAnno("小明")
    private String name;
    private Integer age;
}

 3. 通过反射使用注解,并将注解的值赋值给javabean,从而实现spring中的@Value

package anno_demo1;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author windStop
 * @version 1.0
 * @description 测试注解
 * @date 2024年07月27日15:00:47
 */
public class Test{
    public static void main(String[] args) throws Exception{
        Class<Student> studentClass = Student.class;
        Student student = studentClass.getDeclaredConstructor().newInstance();
        Method[] declaredMethods = studentClass.getDeclaredMethods();
        for (Method method : declaredMethods) {
            method.setAccessible(true);
            // 判断方法上是否存在Init注解,存在就返回true,否则返回false
            if (method.isAnnotationPresent(MyAnno.class)) {
                // 返回该方法的注解
                MyAnno init = method.getAnnotation(MyAnno.class);
                // 执行这个方法并且将注解的值给其赋值
                method.invoke(student, init.value());
            }
        }
        Field name = studentClass.getDeclaredField("name");
        name.setAccessible(true);
        MyAnno annotation = name.getAnnotation(MyAnno.class);
        name.set(student,annotation.value());
        System.out.println(student);
    }
}

2.3 用途

  • 作用

    • 元数据标记:注解提供了一种在代码中添加元数据(metadata)的方式,用于描述类、方法、字段等程序元素的信息。
    • 编译时处理:可以在编译时和运行时通过反射机制获取注解信息,从而影响程序的行为。
    • 代码分析工具:许多开发工具和框架利用注解来配置和扩展应用,例如 Spring 框架中的 @Autowired@RequestMapping 等。
  • 在项目中的应用

    • 配置管理:用于配置和管理各种应用程序的行为和属性,如数据源配置、事务管理等。
    • 代码分析和验证:通过自定义注解来实现代码风格检查、安全检查等。
    • 框架集成:许多流行的框架和库都使用注解来简化配置和扩展,如 Spring、JUnit 等。
    • 文档生成:通过注解生成文档,如使用 Swagger 的 @Api 和 @ApiOperation 注解。

2.4 使用反射获得是否被指定注解修饰

1. 判断类是否被注解修饰
// 首先判断Test类上是否使用了TestAnnotation注解
boolean hasAnnotation = Test.class.isAnnotationPresent(TestAnnotation.class);
 2. 判断方法是否被注解修饰
method.isAnnotationPresent(MyAnno.class)

下述是一个代码找出所有被@MyAnno修饰的方法 ,并将value赋值给形参

public static void main(String[] args) throws Exception{
        Class<Student> studentClass = Student.class;
        Student student = studentClass.getDeclaredConstructor().newInstance();
        Method[] declaredMethods = studentClass.getDeclaredMethods();
        for (Method method : declaredMethods) {
            method.setAccessible(true);
            // 判断方法上是否存在Init注解,存在就返回true,否则返回false
            if (method.isAnnotationPresent(MyAnno.class)) {
                // 返回该方法的注解
                MyAnno init = method.getAnnotation(MyAnno.class);
                // 执行这个方法并且将注解的值给其赋值
                method.invoke(student, init.value());
            }
        }
}

 3. 判断属性是否被注解修饰

//判断属性有没有被注解修饰
        boolean annotationPresent = name.isAnnotationPresent(MyAnno.class);

取出name属性并将其上面的MyAnno注解的值赋值给其成员变量

        Student student = studentClass.getDeclaredConstructor().newInstance();        
        Field name = studentClass.getDeclaredField("name");
        name.setAccessible(true);
        
        MyAnno annotation = name.getAnnotation(MyAnno.class);
        name.set(student,annotation.value());
        System.out.println(student);

2.5 模拟tomcat输入对应的路径执行对应的方法 

1. 自定义@Controller注解

介绍使用到的元注解

@Target(ElementType.TYPE):该注解用于类上
@Documented:会生成到javadoc中
@Retention(RetentionPolicy.RUNTIME):该注解会被保留到运行时期

package anno_tomcat.tomcat_method;

import java.lang.annotation.*;

/**
 * @author windStop
 * @version 1.0
 * @description 标记注解:标记是一个请求控制器
 * @date 2024年07月27日20:04:38
 */
@Target(ElementType.TYPE)
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {
    String[] value() default "";
}
2. 自定义@RequestMapping注解

自定在方法上。生效到运行时期

package anno_tomcat.tomcat_method;

import java.lang.annotation.*;

/**
 * @author windStop
 * @version 1.0
 * @description 映射路径注解
 * @date 2024年07月27日20:11:44
 */
@Target(ElementType.METHOD)
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
    String value();
}
 3. 自定两个控制器
package anno_tomcat.tomcat_method;

/**
 * @author windStop
 * @version 1.0
 * @description 测试:给方法声明注解的作用,获取URL和请求路径
 * @date 2024年07月27日20:03:51
 */
@SuppressWarnings("all")
@Controller
public class StudentController {

    @RequestMapping("/addStudent")
    public boolean addStudent(int id){
        System.out.println("学生添加成功");
        return true;
    }

    @RequestMapping("/updateStudent")
    public boolean updateStudent(int id){
        System.out.println("学生修改成功");
        return true;
    }

    @RequestMapping("/deleteStudent")
    public boolean deleteStudent(int id){
        System.out.println("学生删除成功");
        return true;
    }

    @RequestMapping("/getStudent")
    public Student getStudent(String name){
        System.out.println("学生查询成功");
        return new Student(name,18);
    }
}
package anno_tomcat.tomcat_method;

/**
 * @author windStop
 * @version 1.0
 * @description 测试book
 * @date 2024年07月27日21:21:38
 */
@Controller
public class BookController {
    @RequestMapping("/showBook")
    public void show(int a){
        System.out.println("show方法");
    }

    @RequestMapping("/addBook")
    public void addBook(int a) {
        System.out.println("正在添加图书");
    }
}
 4. 模拟tomcat

我现在是tomcat开发程序员,我现在要使用未来某个时刻的二逼程序员写的代码。

思路分析:

  1. 首先,我不知道他是什么时候写的,并且类名叫什么
  2. 但我可以给他提供一个规范,就是实现@Controller注解,并且项目在当前包中,路径映射写在@RequestMapping中。
  3. 最后,他只要符合我的要求,我就可以使用他的代码。

代码分析:

  1. 不知道程序员什么时候写,那就需要使用反射的Class.forName(className),来在运行时动态加载类的机制,适合需要根据运行时条件加载不同类的场景。
  2. 扫描含有@Controller注解的全类名,进行获取反射类,然后获取出所有方法,在扫描出含有@RequestMapping,注解并且提取其属性和你输入属性对比,相同调用其注解标识的方法。
package anno_tomcat.tomcat_method;


import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

/**
 * @author windStop
 * @version 1.0
 * @description 模拟tomcat,使用用户的代码
 * @date 2024年07月27日20:14:06
 */
public class TomcatDemo {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        //1. 获取全类名
        List<String> listClass = findClass("anno_tomcat.tomcat_method");
        String url = sc.next();//用户输入的url
        for (String className : listClass) {
            Class<?> aClass = Class.forName(className);
            //2. 判断是否包含Controller注解
            if (aClass.isAnnotationPresent(Controller.class)) {
                //创建javabean对象
                Object o = aClass.getDeclaredConstructor().newInstance();
                //3. 根据输入的全类名执行对应的方法
                 //忽略 用户输入的 /
//                url = url.replace("/", "");
                Method[] methods = aClass.getDeclaredMethods();
                for (Method method : methods) {
                    //4. 只查询被@RequestMapping修饰的方法
                    if (method.isAnnotationPresent(RequestMapping.class)){
                        // 获取注解,这个相当于是真正的拿到注解了,只有获取到这个才能获取到注解当中设置的值
                        RequestMapping annotation = method.getAnnotation(RequestMapping.class);
                        if (url.equals(annotation.value())){
                            method.invoke(o,0);
                        }
                    }
                }
            }
        }

    }

    /**
     * 查找指定路径的全类名
     * @return
     */
    public static List<String> findClass(String packageName){//指定要查看的包名
        String packagePath = packageName.replace('.', '\\'); // 将包名转换为路径格式
        List<String> result = new ArrayList<>();
        // 获取当前工作目录下指定包的路径
        String currentDirectory = System.getProperty("user.dir");
        String packageDirectoryPath = currentDirectory + "\\src\\" + packagePath;
        File packageDirectory = new File(packageDirectoryPath);
        // 检查该路径是否存在且为目录
        if (packageDirectory.exists() && packageDirectory.isDirectory()) {
            // 获取目录下的文件列表
            File[] files = packageDirectory.listFiles();//获得所有子文件
            if (files != null) {
                for (File file : files) {
                    String str = packageName;//包名
                    str = str + "." + file.getName();//全类名
                    //删除.java后缀
                    //找出最后一个点的位置
                    int lastIndex = str.lastIndexOf('.');
                    str = str.substring(0,lastIndex);
                    result.add(str);
                }
            } else {
                System.out.println("在包中找不到文件 " + packageName);
            }
        } else {
            System.out.println("包 " + packageName + " 没有找到");
        }
        return result;
    }
}

总结

举报

相关推荐

0 条评论