枚举与注解

 1 枚举

1.1 实现,而非继承

所有的enum都继承自java.lang.Enum类,由于Java不支持多重继承,所以enum不能再继承其他类。

然后,在创建一个新的enum时,可以同时实现一个或多个接口:

public class EnumTest {

    interface Car {
        void driver();
    }

    enum Audi implements Car {

        A4 {
            @Override
            public void driver() {
                System.out.println("A4");
            }
        },
        A6 {
            @Override
            public void driver() {
                System.out.println("A6");
            }
        },
        A8 {
            @Override
            public void driver() {
                System.out.println("A8");
            }
        };
    }

    @Test
    public void test01() {
        for (Audi audi : Audi.values()) audi.driver();
    }

}

1.2 EnumSet

其存储结构elements 并未直接存枚举本身,而是位标志。long(64位)类型。

1.2.1 位向量

是有一些二进制位组成的向量。可以用很少的内存来存储变量。

例如 a=[01101001],从右边数起,第0、3、5、6位是1,所以就表示0,3,5,6这四个数。所以a表示为{0,3,5,6}。

使用一个大数组,其需要存储0-1000(N)的值,若数组类型类型为int(java中int类型通常占4个字节,一个字节是8位)。则数组定义为int a[N/32+1]。

显然,a[0]可以表示0~31的整数。

1.2.2 源码分析

public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
    Enum<?>[] universe = getUniverse(elementType);
    if (universe == null)
        throw new ClassCastException(elementType + " not an enum");

    if (universe.length <= 64)
        return new RegularEnumSet<>(elementType, universe);
    else
        return new JumboEnumSet<>(elementType, universe);
} //创建一个空的EnumSet

根据传入的枚举类型判断组成长度。

RegularEnumSet

private long elements = 0L; //存储枚举值

public boolean add(E e) {
    typeCheck(e);

    long oldElements = elements;
    elements |= (1L << ((Enum<?>)e).ordinal());
    return elements != oldElements;
}  //往set添加枚举

public boolean remove(Object e) {
    if (e == null)
        return false;
    Class<?> eClass = e.getClass();
    if (eClass != elementType && eClass.getSuperclass() != elementType)
        return false;

    long oldElements = elements;
    elements &= ~(1L << ((Enum<?>)e).ordinal());
    return elements != oldElements;
}  //从set中删除枚举

public boolean contains(Object e) {
    if (e == null)
        return false;
    Class<?> eClass = e.getClass();
    if (eClass != elementType && eClass.getSuperclass() != elementType)
        return false;

    return (elements & (1L << ((Enum<?>)e).ordinal())) != 0;
}  //在set中是否存在该枚举

public int size() {
    return Long.bitCount(elements);
}  //set中包含的枚举数量 Long.bitCount方法返回有多少个1

JumboEnumSet

private long elements[]; //存储枚举值

public boolean add(E e) {
    typeCheck(e);

    int eOrdinal = e.ordinal();
    int eWordNum = eOrdinal >>> 6;

    long oldElements = elements[eWordNum];
    elements[eWordNum] |= (1L << eOrdinal);
    boolean result = (elements[eWordNum] != oldElements);
    if (result)
        size++;
    return result;
}  //添加枚举

1.3 EnumMap

是一种特殊的Map,它要求其中的键(key)必须来自一个enum。

1.4 常量相关的方法

为enum定义一个或多个abstract方法,然后为每个enum实例实现该抽象方法。

public class EnumTest2 {

    enum People {
        Student {
            @Override
            void speak() {
                System.out.println("学生");
            }
        },

        Teacher {
            @Override
            void speak() {
                System.out.println("老师");
            }
        };

        abstract void speak();
    }

}

2 注解

2.1 基本语法

2.1.1 定义注解

@Target(ElementType.METHOD) // 元数据,定义注解将应用于哪里
@Retention(RetentionPolicy.RUNTIME) // 元数据,定义注解在哪个级别可用
public @interface UseCase {
    int id(); // 用来表示某些值,当分析注解时,程序可利用这些值
    String description() default "没有描述"; //可指定默认值
}

2.1.2 元注解

@Target

表示该注解可以用于什么地方

@Retention

表示需要在什么级别保存该注解信息

@Documented

将此注解包含在Javadoc中

@Inherited

允许子类继承父类中的注解

元注解专职负责注解其他的注解

2.2 编写注解处理器

注解不支持继承。

2.2.1 注解元素

注解元素可以的类型有:所有基本类型(int,float,boolean等)、String、Class、enum、Annotation及这些类型的数组。

对于非基本类型的元素,无论是在源代码中声明时,或是在注解接口中定义默认值时,都不能以null作为其值。

2.2.2 实现处理器

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Constraints {
    boolean primaryKey() default false;
    boolean allowNull() default true;
    boolean unique() default false;
}

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLString {
    int value() default 0;
    String name() default "";
    Constraints constraints() default @Constraints;
}

public class Student {

    @SQLString(15)
    private String name;

    @SQLString(name = "username")
    private String username;

    @SQLString(constraints = @Constraints(unique = true))
    private String address;

    public static void main(String[] args) {
        Class<Student> studentClass = Student.class;
        for (Field field: studentClass.getDeclaredFields()) {
            Annotation[] annotations = field.getDeclaredAnnotations();
            System.out.print(field.getName() + ":");
            for (Annotation annotation: annotations) {
                if (annotation instanceof SQLString) {
                    SQLString sqlString = (SQLString) annotation;
                    System.out.print("value:" + sqlString.value() + "; ");
                    System.out.print("name:" + sqlString.name() + "; ");
                    System.out.print("constraints:" + sqlString.constraints() + "; ");
                }
            }
            System.out.println();
        }
    }
}
// 输出
//name:value:15; name:; constraints:@study01.Constraints(allowNull=true, unique=false, primaryKey=false);
//username:value:0; name:username; constraints:@study01.Constraints(allowNull=true, unique=false, primaryKey=false);
//address:value:0; name:; constraints:@study01.Constraints(allowNull=true, unique=true, primaryKey=false);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值