主要记录一下枚举类和注解的使用场景
一.枚举类
特点
- Java 枚举是一个特殊的类,一般用来生成有限个实例供外界调用,Java 枚举类使用 enum 关键字来定义,各个实例间使用逗号 , 来分割.
- 所有的实例变量定义在第一行,默认使用 public static final 修饰.
- 枚举类的构造器默认都是 private 修饰的,所以不能创建新的实例对象.
- 枚举类提供 values() 方法,可以获取到所有的实例对象.
- 使用enum定义的枚举类默认继承了java.lang.Enum类,而不是默认继承Object类,因此枚举类不能显示继承其他父类。
优势
- 枚举类相比较于静态常量,可以很方便的打印出每个数字对应的含义
- 可以在枚举类的静态代码块中,对所有的实例对象进行一些操作,比如生成目录.
使用场景
- 替代静态常量
- 自动生成目录
自动生成目录代码
package com.example.springboot01.util;
import java.io.File;
public enum FileCatalog {
UPS(1),FEDEX(2);
// 创建目录
static {
FileCatalog[] fileCatalogs = FileCatalog.values();
for (FileCatalog fileCatalog: fileCatalogs) {
String path = "D:\\workspace" + File.separator + fileCatalog.toString();
File file = new File(path);
if (!file.exists()) {
file.mkdirs();
}
}
}
private final int a;
FileCatalog(int a) {
this.a = a;
}
public int getValue() {
return this.a;
}
}
上述代码中可以通过 FileCatallog.UPS.toString() 来获取 “UPS” 字符串.
二.注解
特点
- 注解是一种特殊的接口, 使用 @interface 关键字定义
- 注解里面的变量定义和类里面有些不同,在变量后面需要增加圆括号 (), 并且可以设置默认值.
- 注解有4个元注解,分别是 @Retention 表示在什么级别保存该注解信息, @Target 表示该注解用于什么地方, @Documented 将此注解包含在 javadoc 中, @Inherited 允许子类继承父类中的注解.
- 注解对标注的代码不会产生任何影响,想要发挥注解的作用,可以通过反射来完成.
优势
- 通过注解可以很方便的区分出哪些代码需要进行特殊操作
- 使用方便,只要在代码前加上注解就能实现特定功能
使用场景
- 可以配合面向切面编程,实现日志记录,安全校验等功能.
- 可以实例化对象.
实例化对象代码
网上找的一个例子
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitProvider {
/*供应商编号*/
public int id() default -1;
/*供应商名称*/
public String name() default "";
/*供应商地址*/
public String address() default "";
}
@FruitProvider(id = 1728, name = "why", address = "shenzhen")
public class Apple {
private int appleID;
private String appleProvidername;
private String appleprovideraddress;
}
public class FruitInfoUtil {
public static Apple getAApple(Class<?> clazz) throws Exception{
FruitProvider fb = clazz.getAnnotation(FruitProvider.class);//通过反射获取处理注释
//通过newInstance()生成Apple实例,利用反射的结果进行设置
Apple ap = (Apple)clazz.newInstance();
ap.setAppleID(fb.id());
ap.setAppleProvidername(fb.name());
ap.setAppleprovideraddress(fb.address());
return ap;
}
}
public class Main {
public static void main(String[] args) throws Exception{
Apple a = FruitInfoUtil.getAApple(Apple.class);
System.out.println("苹果商的ID为:"+a.getAppleID());
System.out.println("苹果商的名字为:"+a.getAppleProvidername());
System.out.println("苹果商的地址为:"+a.getAppleprovideraddress());
}
}
日志记录
// 注解类
package com.example.springboot01.util;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface TestAnnotation {
boolean printInstance() default false;
}
// 切面类
package com.example.springboot01.util;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Aspect
@Component
public class TestAspect {
@Pointcut("@annotation(com.example.springboot01.util.TestAnnotation)")
public void pointcut() {
}
@Before("pointcut()")
public void before(JoinPoint joinPoint) {
try {
String methodName = joinPoint.getSignature().getName();
//Class clazz = joinPoint.getThis().getClass();
Class clazz = Class.forName("com.example.springboot01.HomeController");
Method m = clazz.getMethod(methodName);
if (m.isAnnotationPresent(TestAnnotation.class)) {
if (m.getAnnotation(TestAnnotation.class).printInstance()) {
System.out.println(clazz.getName());
}
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
// 测试方法
@TestAnnotation(printInstance = true)
public Set<String> getKeys() throws InterruptedException {
Set<String> set = redisTemplate.keys("*");
Iterator<String> iterator = set.iterator();
while(iterator.hasNext()) {
if(iterator.next().matches("spring:session.*")) {
iterator.remove();
}
}
return set;
}
- 注解想起作用,一般都是通过反射来完成的.
- 先是获取类对象,再获取这个类的指定方法,判断这个方法是否标注了指定的注解,获取到注解里面的值,根据不同的值来执行不同的处理逻辑.