7.1 枚举类
枚举类的对象只有有限个确定数值,如星期、性别、季节等。构造器必须使用private,所有实例必须在枚举类中显式列出,系统将自动为其添加public static final修饰,且必须在枚举类的第一行声明枚举类对象。
switch表达式中可使用enmu定义的枚举类对象作为表达式, case 子句可以直接使用枚举值的名字。
public enum SeasonEnum {SPRING("春天","春风又绿江南岸"),SUMMER("夏天","映日荷花别样红"),AUTUMN("秋天","秋水共长天一色"),WINTER("冬天","窗含西岭千秋雪"); // 注意这里的符号private final String seasonName;private final String seasonDesc;private SeasonEnum(String seasonName, String seasonDesc) {this.seasonName = seasonName;this.seasonDesc = seasonDesc;}public String getSeasonName() {return seasonName;}public String getSeasonDesc() {return seasonDesc;}}
// 例子SeasonEnum summer = SeasonEnum.SUMMER;SeasonEnum[] values = SeasonEnum.values(); // 返回枚举类型的对象数组
7.2 注解
注解(Annotation)是代码里的特殊标记,可在编译、 类加载、 运行时被读取, 并根据注解类型执行相应处理。通过使用注解,程序员可以在不改变原有逻辑的情况下, 在源文件中嵌入一些补充信息,代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证或部署。
7.2.1 注解的使用情景
注解通常用于标记过时功能,忽略警告,配置应用程序(如XML配置)等。未来的开发模式都是基于注解的,一定程度上可以说:框架 = 注解 + 反射 + 设计模式。
示例一:生成文档相关的注解
@author@version@see // 相关主题@since // 从哪个版本开始增加的@Description // 功能描述@date// 仅用于方法的标记,@param和@exception可以并列多个@param // 对方法中某参数的说明@return // 对方法返回值的说明@exception // 对方法可能抛出的异常进行说明@param 形参名 形参类型 形参说明@return 返回值类型 返回值说明@exception 异常类型 异常说明
package com.annotation.javadoc;/*** @author shkstart* @version 1.0* @see Math.java*/public class JavadocTest {/*** 程序的主方法,程序的入口* @param args String[] 命令行参数*/public static void main(String[] args) {}/*** 求圆面积的方法* @param radius double 半径值* @return double 圆的面积*/public static double getArea(double radius){return Math.PI * radius * radius;}}
示例二:在编译时进行格式检查(JDK内置的三个基本注解)
@Override // (凌驾、覆盖)标明是重写方法,不写也可能为重写方法@Deprecated // (过时)表明不推荐使用@SuppressWarnings // 抑制编译器警告
package com.annotation.javadoc;public class AnnotationTest{public static void main(String[] args) {@SuppressWarnings("unused")int a = 10;}@Deprecatedpublic void print(){System.out.println("过时的方法");}@Overridepublic String toString() {return "重写的toString方法()";}}
示例三:跟踪代码依赖性,实现替代配置文件功能
在Java Web中会用到Servlet接口,通过注解则无需在web.xml中进行Servlet部署
7.2.2 自定义注解
自定义注解使用 @interface 关键字,其自动继承java.lang.annotation.Annotation接口,注解的成员变量以无参数方法声明,我们称为配置参数。类型只能是八种基本数据类型、String、Class、Enum、Annotation。
可以在定义注解的成员变量时为其指定初始值,指定成员变量的初始值使用 default,如果只有一个参数成员,建议使用参数名value。如果定义的注解含有配置参数,那么使用时必须指定参数值,除非它有默认值。格式是“参数名 = 参数值”,如果只有一个参数成员,且名称为value,可以省略“value=” 。
没有成员定义的注解称为标记; 包含成员变量的注解称为元数据 Annotation。
// 例子1 成员变量无参public @interface MyAnnotation{String value(); // 成员变量以无参方法声明,定义名字和类型}@MyAnnotation( value = "hello") // 注解无默认配置参数,必须指定参数@MyAnnotation("hello") // 仅一个变量且名称为value,省略变量名// 例子2 成员变量有参数public @interface MyAnnotation{String value() default "hello"; // 成员变量以无参方法声明,定义名字和类型并指定初始值}@MyAnnotation( value = "hi")@MyAnnotation// 例子三 无成员变量作为特殊标识public @interface MyAnnotation{}@MyAnnotation
7.2.3 JDK中的元注解
元注解是对现有的注解进行解释说明的注解。
@Target(ElementType.METHOD)@Retention(RetentionPolicy.SOURCE)public @interface Override{}
- Retention(留存):指定注解的生命周期,其包含一个 RetentionPolicy 类型的成员变量:
- RetentionPolicy.SOURCE:在源文件中有效,在class文件中不再加载
- RetentionPolicy.CLASS:在class文件中有效,不会将此注解加载到内存。 这是默认值
- RetentionPolicy.RUNTIME:在运行时有效,当运行程序时, JVM会保留注释。程序可以通过反射获取该注释。
Target(目标):指定注解能用于修饰哪些程序元素。可用
,进行多种修饰:CONSTRUCTOR:用于描述构造器PACKAGE:用于描述包FIELD:用于描述域PARAMETER:用于描述参数LOCAL_VARIABLE:用于描述局部变量TYPE:用于描述类、接口(包括注解类型)或enum声明METHOD:用于描述方法
Documented:指定注解类将被javadoc工具提取成文档。默认情况下,javadoc是不包括注解的。 定义为Documented的注解必须设置Retention值为RUNTIME。
Inherited:修饰的注解将具有继承性。如果某个类使用了其修饰的 Annotation, 则其子类将自动具有该注解。
7.2.4 JDK8中注解的新特性
可重复注解: ```java // JDK8前声明重复注解 public @interface MyAnnotations{ MyAnnotation[] value(); } @MyAnnotations({@MyAnnotation(value=”hi”),@MyAnnotation(value=”hello”)})
// JDK8写法
@Repeatable(MyAnnotations.class) // 此时两种注解声明周期应当相同,修饰类型也应当相同,即Retention、Target等元注解必须相同
public @interface MyAnnotation{
String value();
}
public @interface MyAnnotations{
MyAnnotation[] value();
}
2. 用于类型的注解:在Java 8之前,注解只能在声明的地方所使用,Java8开始,注解可以应用在任何地方。```java/* jdk8新加入的Target枚举值* TYPE_PARAMETER:表示该注解能写在类型变量的声明语句中(如:泛型声明)* TYPE_USE:表示该注解能写在使用类型的任何语句中。*/// 例子1public class TestTypeDefine<@TypeDefine() U> {private U u;public <@TypeDefine() T> void test(T t){}}@Target({ElementType.TYPE_PARAMETER})@interface TypeDefine{}// 例子2@MyAnnotationpublic class AnnotationTest<U> {@MyAnnotationprivate String name;public static void main(String[] args) {AnnotationTest<@MyAnnotation String> t = null;int a = (@MyAnnotation int) 2L;}public static <@MyAnnotation T> void method(T t) {}public static void test(@MyAnnotation String arg) throws @MyAnnotation Exception {}}@Target(ElementType.TYPE_USE)@interface MyAnnotation {}
