第八章、枚举与注解

148 阅读6分钟

1、枚举

1.1 介绍

枚举就是一组常量的集合,有的时候我们的变量可能只有几个值,比如12个月、春夏秋冬等,那么我们完全可以把它们设置成一个枚举类,枚举类使用enum关键字,一些细节:

  • 枚举类不需要提供setXXX方法,因为它的对象一般是只读对象
  • 对枚举对象属性使用final static修饰,实现底层优化
  • 枚举类对象是常量,所以用大写
  • 枚举对象根据需要,可以有多个属性
public class Enumeration01 {
    public static void main(String[] args) {
        System.out.println(Season1.SPRING);
        System.out.println(Season2.SPRING);
    }
}

class Season1{
    private String name;
    private String desc;

    public Season1(String name, String desc) {
        this.name = name;
        this.desc = desc;
    }

    public static final Season1 SPRING = new Season1("春天","温暖");
    public static final Season1 SUMMER = new Season1("夏天","炎热");
    public static final Season1 AUTUMN = new Season1("秋天","萧瑟");
    public static final Season1 WINTER = new Season1("冬天","寒冷");

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("Season1{");
        sb.append("name='").append(name).append('\'');
        sb.append(", desc='").append(desc).append('\'');
        sb.append('}');
        return sb.toString();
    }
}

enum Season2{
    SPRING("春天","很温暖"),
    SUMMER("夏天","很炎热"),
    AUTUMN("秋天","很萧瑟"),
    WINTER("冬天","很寒冷");

    private String name;
    private String desc;

    Season2(String name, String desc) {
        this.name = name;
        this.desc = desc;
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("Season2{");
        sb.append("name='").append(name).append('\'');
        sb.append(", desc='").append(desc).append('\'');
        sb.append('}');
        return sb.toString();
    }
}

1.2 详解

细节:

  • 当我们使用enum关键字开发一个枚举类时,默认会继承Enum类, 而且是一个final类
  • 如果使用无参构造器创建枚举对象,则实参列表和小括号都可以省略
  • 当有多个枚举对象时,使用,间隔,最后有一个分号结尾
  • 枚举对象必须放在枚举类的行首
  • enums既然隐式继承了Enum,所以就不能再继承其他类了,但可以实现接口

1.3 enums方法

image.png

实例:

public class EnumDetails {
    public static void main(String[] args) {
        System.out.println(Gender.MAN);
        System.out.println(Gender.MAN.compareTo(Gender.WOMAN));//-1
        System.out.println(Gender.MAN.ordinal());//0
        System.out.println(Gender.WOMAN.ordinal());//1
        System.out.println(Gender.MAN.name());//MAN
        System.out.println(Arrays.toString(Gender.values()));
        Gender man = Gender.valueOf("MAN");
        System.out.println(man);
    }
}

enum Gender{
    MAN(true,"男的"),
    WOMAN(false,"女的");

    private boolean gender;
    private String desc;

    Gender(boolean gender, String desc) {
        this.gender = gender;
        this.desc = desc;
    }
}

2、注解

2.1 介绍

注解(Annotation)也被称为元数据(Metadata),用于修饰解释 包、类、方法、属性、构造器、局部变量等数据信息。

和注释一样,注解不影响程序逻辑,但注解可以被编译或运行,相当于嵌入在代码中的补充信息。

在 JavaSE 中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在 JavaEE 中注解占据了更重要的角 色,例如用来配置应用程序的任何切面,代替 java EE 旧版中所遗留的繁冗代码和 XML 配置等。

2.2 基本注解

三个基本注解:

  • @Override: 限定某个方法,是重写父类方法, 该注解只能用于方法
  • @Deprecated: 用于表示某个程序元素(类, 方法等)已过时
  • @SuppressWarnings: 抑制编译器警告

2.3 @Override注解

@Override方法只适用于方法,而且是检查是否重写了父类的方法。

public class Override_ {
    public static void main(String[] args) {

    }
}

class Father{
    public void bite(){
        System.out.println("father bite me");
    }

    public void speak(){

    }
}

class Son extends Father{
    //@Override 不写也行
    public void bite() {
        super.bite();
    }

    //@Override
    //public void speak1() {
    //    super.speak();
    //}
    //上面这样写就不行,因为speak1()不是重写的方法
}

看一下源码:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {	//JDK5.0后,注解类出现了-->@interface
}

细节:

  • @Override表示指定重写父亲的方法,如果父类没有这个方法,就会报错
  • 如果不写@Override注解,其实也行

2.4 @Deprecated注解

表示某个类、方法、字段、包、参数等已经过时了,不推荐使用但仍然能用。

源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}

实例:

public class Deprecated_ {
    public static void main(String[] args) {
        A.test();
        A a = new A();
        a.test1();
        System.out.println(A.name);
    }

}

@Deprecated
class A{
    @Deprecated
    public static String name = "z";

    //@Deprecated   //代码块不能有
    //{
    //    System.out.println("y");
    //}

//    @Deprecated
    public static void test(){
        System.out.println("test deprcated");
    }

    public void test1(){
        System.out.println("test1 not deprecated");
    }
}

2.5 @SuppressWarnings注解

注解翻译j过来叫做抑制编译器警告,一般是不希望编译器检查某些错误,并给出提示用的。

源码:

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    /**
     * The set of warnings that are to be suppressed by the compiler in the
     * annotated element.  Duplicate names are permitted.  The second and
     * successive occurrences of a name are ignored.  The presence of
     * unrecognized warning names is <i>not</i> an error: Compilers must
     * ignore any warning names they do not recognize.  They are, however,
     * free to emit a warning if an annotation contains an unrecognized
     * warning name.
     *
     * <p> The string {@code "unchecked"} is used to suppress
     * unchecked warnings. Compiler vendors should document the
     * additional warning names they support in conjunction with this
     * annotation type. They are encouraged to cooperate to ensure
     * that the same names work across multiple compilers.
     * @return the set of warnings to be suppressed
     */
    String[] value();
}

常用参数:

  • all:抑制所有警告
  • boxing:抑制与封装/拆装作业相关的警告
  • cast:抑制与强制转型作业相关的警告
  • dep-ann:抑制与淘汰注释相关的警告
  • deprecation:抑制与淘汰的相关警告
  • fallthrough:抑制与switch陈述式中遗漏break相关的警告
  • finally:抑制与未传回finally区块相关的警告
  • hiding:抑制与隐藏变数的区域变数相关的警告
  • incomplete-switch:抑制与switch陈述式(enum case)中遗漏项目相关的警告
  • javadoc:抑制与javadoc相关的警告
  • nls:抑制与非nls字串文字相关的警告
  • null:抑制与空值分析相关的警告
  • rawtypes:抑制与使用raw类型相关的警告
  • resource:抑制与使用Closeable类型的资源相关的警告
  • restriction:抑制与使用不建议或禁止参照相关的警告
  • serial:抑制与可序列化的类别遗漏serialVersionUID栏位相关的警告
  • static-access:抑制与静态存取不正确相关的警告
  • static-method:抑制与可能宣告为static的方法相关的警告
  • super:抑制与置换方法相关但不含super呼叫的警告
  • synthetic-access:抑制与内部类别的存取未最佳化相关的警告
  • sync-override:抑制因为置换同步方法而遗漏同步化的警告
  • unchecked:抑制与未检查的作业相关的警告
  • unqualified-field-access:抑制与栏位存取不合格相关的警告
  • unused:抑制与未用的程式码及停用的程式码相关的警告
@SuppressWarnings({"unchecked","unused","rawtypes,all"})
public class SuppressWarning_ {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("zhangsan");
        list.add("lisi");
        list.add("wangwu");
        list.add("zhaoliu");
        list.add("");
    }
}

3、元注解

3.1 基本介绍

元注解用于修饰其他注解的。就是一下这四种:

  • Retention:指定注解的作用范围,三种 SOURCE,CLASS,RUNTIME
  • Target:指定注解可以在哪些地方使用
  • Documented:指定该注解是否会在 javadoc 体现
  • Inherited:子类会继承父类注解

3.2 @Retention注解

用于修饰一个annotation可以保留多长时间,其中@Retention包含一个RetentionPolicy类型的成员变量,它的值可以是:

  • RetentionPolicy.SOURCE: 编译器使用后,直接丢弃这种策略的注释
  • RetentionPolicy.CLASS: 编译器将把注解记录在class文件中. 当运行Java程序时, JVM不会保留注解。 这是默认值
  • RetentionPolicy.RUNTIME: 编译器将把注解记录在class文件中 . 当运行Java程序时, JVM会保留注解. 程序可以通过反射获取该注解

比如Override注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {	//JDK5.0后,注解类出现了-->@interface
}

3.3 @Target注解

用来修饰annotation可以修饰哪些元素,包含一个名为value的成员变量。

比如:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}

3.4 @Documented注解

用于指定该元注解修饰的注解类会被javadoc提取成文档。生成文档是会看到该注解。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}

3.5 @Inherited注解

被这个元注解修饰的注解会具有继承性,如果某一个类被使用到@Inherited注解修饰的对象,子类将自动具有该注解,实际应用不多。