Java基础(十)——枚举与注解
一、枚举
1、介绍
枚举类:类的对象只有有限个,确定的。当需要定义一组常量时,强烈建议使用枚举类。如果枚举类中只有一个对象,则可以作为单例模式的实现。
使用 enum 定义的枚举类默认继承了 java.lang.Enum类,因此不能再继承其他类。
2、枚举的实现
代码示例:方式一,JDK 5.0 之前,自定义枚举类
- 1 public class SeasonEnum {
- 2
- 3 // 枚举当前类的多个对象
- 4 public static final SeasonEnum SPRING = new SeasonEnum("01", "春天");
- 5 public static final SeasonEnum SUMMER = new SeasonEnum("02", "夏天");
- 6 public static final SeasonEnum AUTUMN = new SeasonEnum("03", "秋天");
- 7 public static final SeasonEnum WINTER = new SeasonEnum("04", "冬天");
- 8
- 9 private SeasonEnum(String code, String desc) {
- 10 this.code = code;
- 11 this.desc = desc;
- 12 }
- 13
- 14 private final String code;
- 15 private final String desc;
- 16
- 17 public String getCode() {
- 18 return code;
- 19 }
- 20
- 21 public String getDesc() {
- 22 return desc;
- 23 }
- 24 }
代码示例:方式二,JDK 5.0,可以使用 enum 关键字定义枚举
- 1 public enum SeasonEnum {
- 2
- 3 // 枚举当前类的多个对象
- 4 SPRING("01", "春天"),
- 5 SUMMER("02", "夏天"),
- 6 AUTUMN("03", "秋天"),
- 7 WINTER("04", "冬天");
- 8
- 9 public static final Map<String, SeasonEnum> map = new HashMap<>();
- 10
- 11 static {
- 12 for (SeasonEnum e : values()) {
- 13 map.put(e.code, e);
- 14 }
- 15 }
- 16
- 17 SeasonEnum(String code, String desc) {
- 18 this.code = code;
- 19 this.desc = desc;
- 20 }
- 21
- 22 private final String code;
- 23 private final String desc;
- 24
- 25 public String getCode() {
- 26 return code;
- 27 }
- 28
- 29 public String getDesc() {
- 30 return desc;
- 31 }
- 32
- 33 }
3、枚举实现接口
- 1 public enum SeasonEnum implements Info {
- 2
- 3 // 枚举当前类的多个对象
- 4 SPRING("01", "春天") {
- 5 @Override
- 6 public void show() {
- 7 System.out.println("春暖花开");
- 8 }
- 9 },
- 10 SUMMER("02", "夏天") {
- 11 @Override
- 12 public void show() {
- 13 System.out.println("夏日炎炎");
- 14 }
- 15 },
- 16 AUTUMN("03", "秋天"),
- 17 WINTER("04", "冬天");
- 18
- 19 SeasonEnum(String code, String desc) {
- 20 this.code = code;
- 21 this.desc = desc;
- 22 }
- 23
- 24 private final String code;
- 25 private final String desc;
- 26
- 27 public String getCode() {
- 28 return code;
- 29 }
- 30
- 31 public String getDesc() {
- 32 return desc;
- 33 }
- 34
- 35 public void show() {
- 36 System.out.println("我的天气");
- 37 }
- 38
- 39 }
- 40
- 41 interface Info {
- 42 void show();
- 43 }
4、API
values()方法:返回所有的枚举类型的对象。
valueOf(String str):检查该字符串是不是枚举类对象的"名字"。如不是,会有运行时异常:IllegalArgumentException。
toString():返回当前枚举类对象常量的名称。
二、注解
1、介绍
从 JDK 5.0 开始,Java 增加了对元数据(MetaData)的支持,也就是Annotation(注解)。
Annotation 其实就是代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。通过使用 Annotation,程序员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息。代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证或者进行部署。
一定程度上,可以说:框架 = 注解 + 反射 + 设计模式。
2、示例
示例一、生成文档相关
@author:标明开发该类模块的作者,多个作者之间使用,分割。
@version:标明该类模块的版本。
@see:参考转向,也就是相关主题。
@since:从哪个版本开始增加的。
@param:对方法中某参数的说明,如果没有参数就不能写。
@return:对方法返回值的说明,如果方法的返回值类型是void就不能写。
@exception:对方法可能抛出的异常进行说明,如果方法没有用throws显式抛出的异常就不能写。
示例二、在编译时进行格式检查(JDK内置的三个基本注解)
@Override:限定重写父类方法,该注解只能用于方法。
@Deprecated:用于表示所修饰的元素(类,方法等)已过时。通常是因为所修饰的结构危险或存在更好的选择。
@SuppressWarnings:抑制编译器警告。
3、自定义注解
代码示例:
- 1 @Retention(RetentionPolicy.RUNTIME)
- 2 @Target({ElementType.TYPE, ElementType.FIELD})
- 3 public @interface MyAnnotation {
- 4 String value() default "baidu";
- 5 }
- 6
- 7 @MyAnnotation()
- 8 public class Person {
- 9 }
- 10
- 11 public class Main {
- 12 public static void main(String[] args) {
- 13 // 通过反射获取Person类的注解
- 14 Class<Person> clazz = Person.class;
- 15 MyAnnotation annotation = clazz.getAnnotation(MyAnnotation.class);
- 16
- 17 // 获取注解的值
- 18 String value = annotation.value();
- 19 System.out.println(value); // baidu(输出了默认值)
- 20 }
- 21 }
4、元注解
JDK 的元注解用于修饰其他注解定义。除了上面自定义注解用到的两个,JDK5.0提供了4个标准的元注解,分别是:@Documented、@Inherited、@Retention、@Target。
@Retention:用于指定注解的生命周期,它包含一个RetentionPolicy枚举类型的成员变量。
源码示例:
- 1 @Documented
- 2 @Retention(RetentionPolicy.RUNTIME)
- 3 @Target(ElementType.ANNOTATION_TYPE)
- 4 public @interface Retention {
- 5 /**
- 6 * Returns the retention policy.
- 7 * @return the retention policy
- 8 */
- 9 RetentionPolicy value();
- 10 }
- 11
- 12 public enum RetentionPolicy {
- 13 /**
- 14 * Annotations are to be discarded by the compiler.
- 15 */
- 16 SOURCE,
- 17
- 18 /**
- 19 * Annotations are to be recorded in the class file by the compiler
- 20 * but need not be retained by the VM at run time. This is the default
- 21 * behavior.
- 22 */
- 23 CLASS,
- 24
- 25 /**
- 26 * Annotations are to be recorded in the class file by the compiler and
- 27 * retained by the VM at run time, so they may be read reflectively.
- 28 *
- 29 * @see java.lang.reflect.AnnotatedElement
- 30 */
- 31 RUNTIME
- 32 }
源码中的英文注释写的很清楚,下面翻译一下:
RetentionPolicy.SOURCE:在源文件中有效(即源文件保留),编译器直接丢弃这种策略的注释。
RetentionPolicy.CLASS:在class文件中有效(即class保留),当运行 Java 程序时,JVM不会保留注解。这是默认值。
RetentionPolicy.RUNTIME:在运行时有效(即运行时保留),当运行 Java 程序时,JVM 会保留注释。只有声明为RUNTIME生命周期的注解,才可以通过反射获取该注释。
@Target:用于指定注解能用于修饰哪些程序元素,它包含一个ElementType枚举类型的成员变量。
源码示例:
- 1 @Documented
- 2 @Retention(RetentionPolicy.RUNTIME)
- 3 @Target(ElementType.ANNOTATION_TYPE)
- 4 public @interface Target {
- 5 ElementType[] value();
- 6 }
- 7
- 8 public enum ElementType {
- 9 // 用于修饰类、接口,或者enum声明
- 10 /** Class, interface (including annotation type), or enum declaration */
- 11 TYPE,
- 12
- 13 // 用于修饰域
- 14 /** Field declaration (includes enum constants) */
- 15 FIELD,
- 16
- 17 // 用于修饰方法
- 18 /** Method declaration */
- 19 METHOD,
- 20
- 21 // 用于修饰参数
- 22 /** Formal parameter declaration */
- 23 PARAMETER,
- 24
- 25 // 用于修饰构造器
- 26 /** Constructor declaration */
- 27 CONSTRUCTOR,
- 28
- 29 // 用于修饰局部变量
- 30 /** Local variable declaration */
- 31 LOCAL_VARIABLE,
- 32
- 33 // 用于修饰注解
- 34 /** Annotation type declaration */
- 35 ANNOTATION_TYPE,
- 36
- 37 // 用于修饰包
- 38 /** Package declaration */
- 39 PACKAGE,
- 40
- 41 /**
- 42 * Type parameter declaration
- 43 *
- 44 * @since 1.8
- 45 */
- 46 TYPE_PARAMETER,
- 47
- 48 /**
- 49 * Use of a type
- 50 *
- 51 * @since 1.8
- 52 */
- 53 TYPE_USE
- 54 }
@Documented:用于指定被该注解修饰的类将被 javadoc 工具提取成文档。默认情况下,javadoc是不包括注解的。定义为Documented的注解必须设置Retention值为RUNTIME。
@Inherited:被它修饰的注解将具有继承性。如果某个类使用了被@Inherited 修饰的注解,则其子类将自动具有该注解。
三、JDK8的新特性
1、介绍
Java 8对注解处理提供了两点改进:可重复的注解及可用于类型的注解。此外,反射也得到了加强,在Java8中能够得到方法参数的名称。这会简化标注在方法参数上的注解。
2、可重复注解
代码示例:方式一,JDK8之前
- 1 @Retention(RetentionPolicy.RUNTIME)
- 2 @Target({ElementType.TYPE})
- 3 public @interface MyAnnotation {
- 4 String value() default "baidu";
- 5 }
- 6
- 7 @Retention(RetentionPolicy.RUNTIME)
- 8 @Target({ElementType.TYPE})
- 9 public @interface MyAnnotations {
- 10 MyAnnotation[] value();
- 11 }
- 12
- 13 //@MyAnnotation("xiaoming")
- 14 //@MyAnnotation("xiaohong")
- 15 @MyAnnotations({@MyAnnotation("xiaoming"), @MyAnnotation("xiaohong")})
- 16 public class Person {
- 17 private int age;
- 18
- 19 public void say() {
- 20 }
- 21 }
代码示例:方式二,JDK8之后
- 1 // 注:MyAnnotation的Target和Retention等元注解须与MyAnnotations相同
- 2 @Repeatable(MyAnnotations.class)
- 3 @Retention(RetentionPolicy.RUNTIME)
- 4 @Target({ElementType.TYPE})
- 5 public @interface MyAnnotation {
- 6 String value() default "baidu";
- 7 }
- 8
- 9 @Retention(RetentionPolicy.RUNTIME)
- 10 @Target({ElementType.TYPE})
- 11 public @interface MyAnnotations {
- 12 MyAnnotation[] value();
- 13 }
- 14
- 15 @MyAnnotation("xiaoming")
- 16 @MyAnnotation("xiaohong")
- 17 public class Person {
- 18 private int age;
- 19
- 20 public void say() {
- 21 }
- 22 }
3、类型注解
在Java 8之前,注解只能在声明的地方使用。Java8开始,注解可以应用在任何地方。
ElementType.TYPE_PARAMETER:表示该注解能写在类型变量的声明语句中(如:泛型声明)。
ElementType.TYPE_USE:表示该注解能写在使用类型的任何语句中。
代码示例:TYPE_PARAMETER
- 1 @Retention(RetentionPolicy.RUNTIME)
- 2 @Target({ElementType.TYPE, ElementType.TYPE_PARAMETER})
- 3 public @interface MyAnnotation {
- 4 String value() default "baidu";
- 5 }
- 6
- 7 @MyAnnotation
- 8 public class Person<@MyAnnotation T> {
- 9 private T age;
- 10
- 11 public void say() throws RuntimeException {
- 12 List<String> list = new ArrayList<>();
- 13
- 14 int num = (int) 10L;
- 15 }
- 16 }
代码示例:TYPE_USE
- 1 @Retention(RetentionPolicy.RUNTIME)
- 2 @Target({ElementType.TYPE, ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
- 3 public @interface MyAnnotation {
- 4 String value() default "baidu";
- 5 }
- 6
- 7 @MyAnnotation
- 8 public class Person<@MyAnnotation T> {
- 9 private T age;
- 10
- 11 public void say() throws @MyAnnotation RuntimeException {
- 12 List<@MyAnnotation String> list = new ArrayList<>();
- 13
- 14 int num = (@MyAnnotation int) 10L;
- 15 }
- 16 }
Java基础(十)——枚举与注解的更多相关文章
- 【Java基础】枚举和注解
在Java1.5版本中,引入了两个类型:枚举类型enum type和注解类型annotation type. Num1:用enum代替int常量 枚举类型enum type是指由一组固定的常量组成合法 ...
- java基础解析系列(六)---注解原理及使用
java基础解析系列(六)---注解原理及使用 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列(二)---Integer缓存及 ...
- Java基础之枚举
Java基础之枚举 作为1.5才增加的特性,枚举的使用并不是很多. 枚举其实就是一个比较特殊的类,就如同注解其实也是个特殊的接口一样(注解反编译之后没有了@符号).枚举使用enum关键字声明,通过反编 ...
- 【转】Java基础笔记 – 枚举类型的使用介绍和静态导入--不错
原文网址:http://www.itzhai.com/java-based-notes-introduction-and-use-of-an-enumeration-type-static-impor ...
- 黑马程序员:Java基础总结----枚举
黑马程序员:Java基础总结 枚举 ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 枚举 为什么要有枚举 问题:要定义星期几或性别的变量,该怎么定义?假设用1-7分别 ...
- Java基础十二--多态是成员的特点
Java基础十二--多态是成员的特点 一.特点 1,成员变量. 编译和运行都参考等号的左边. 覆盖只发生在函数上,和变量没关系. Fu f = new Zi();System.out.println( ...
- Java基础十--接口
Java基础十--接口 一.接口的定义和实例 /* abstract class AbsDemo { abstract void show1(); abstract void show2(); } 8 ...
- Java基础之枚举类型Enum的使用
Java基础之枚举类型Enum的使用 定义 public enum AccruedCleanEnum { SPREAD("1","发票"),OTHER(&quo ...
- Java基础加强总结(一)——注解(Annotation)
一.认识注解 注解(Annotation)很重要,未来的开发模式都是基于注解的,JPA是基于注解的,Spring2.5以上都是基于注解的,Hibernate3.x以后也是基于注解的,现在的Struts ...
- 夯实Java基础(十七)——注解(Annotation)
1.注解概述 从JDK5.0开始,Java增加对元数据(MetaData)的支持,也就是注解(Annotation).其实我们早就已经接触过注解了,例如我们经常在Java代码中可以看到 “@Overr ...
随机推荐
- 我的邮箱客户端程序Popmail
05年的时候写了一个邮箱客户端程序.当时主要目的是研究POP3和SMTP协议,同时锻炼自己的网络编程能力.当然了,如果自己写的邮箱客户端能够满足自身的日常工作需要,而不是频繁的登录不同的网页邮箱,那就 ...
- JAVA将byte数组(byte[])按照指定大小分割成多个byte数组
/** * 将byte数组按照指定大小分割成多个数组 * @param bytes 要分割的byte数组 * @param subSize 分割的块大小 单位:字节 * @return 指定大小的by ...
- c++之sigslot库
关于 本文演示环境: win10 + VS2017 1. demo #include <iostream> #include "sigslot.h" using nam ...
- java源码——文件读写和单词统计
本文要解决的问题:"键盘输入一段英语语句,将这段话写入content.txt中,然后输出这段话,并且统计语句中英文单词的数目以及各个单词出现的次数." 分析问题知,核心是文件读写和 ...
- 【LeetCode】1064. Fixed Point 解题报告(C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 暴力求解 日期 题目地址:https://leetco ...
- 【LeetCode】665. 非递减数列 Non-decreasing Array(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 公众号:每日算法题 本文关键词:数组,array,非递减,遍历,python,C++ 目录 题目描述 题目大意 解题方法 一.错误代码 二.举例分析 ...
- Abelian Period
Abelian Period Accepts: 288 Submissions: 984 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 26 ...
- Docker&K8S学习笔记(一)—— Docker安装
最近一年在工作上经常使用Docker与K8S,除了利用其打镜像,部署服务外,还基于Docker与K8S开发了一套CICD流水线平台,为了加深相关知识点的理解,所以从今天开始会定期更新学习笔记,本套学习 ...
- 分布式系统(二)——GFS
分布式存储系统的难点 在存储系统中,为了获得巨大的性能加成,一个很自然的想法就是采用分片(sharding),将数据分割存储到多台服务器上,这样获得了更大的存储容量,而且可以并行地从多台服务器读取数据 ...
- MySQL中视图的定义、原理--触发器
视图概述 视图是一个虚拟表,其内容由查询定义.同真实的表一样,视图包含一系列带有名称的列和行数据.但是,视图并不在数据库中以存储的数据值集形式存在.行和列数据来自由定义视图的查询所引用的表,并且在引用 ...