11枚举和注解
11.1枚举¶
2022年6月9日
12:43
-
引入: 为什么需要枚举
当对于一个类, 我们需要固定的几个对象(例如一个类Season,我们只能有四个对象(春夏秋冬),而不能有额外的对象)
-
枚举: 一组常量的集合 (可以理解为一种特殊的类, 里面只包含一组有限的特定的对象)
-
枚举的实现方法:
自定义类实现枚举¶
注意点: 构造器设为private防止调用, 去掉set方法防止修改, 在类构建固定对象
final class Season {
private String name;
private String desc; //描述
//定义四个固定对象
public static final Season SPRING = new Season("春", "温暖");
public static final Season SUMMER = new Season("夏", "炎热");
public static final Season AUTUMN = new Season("秋", "凉爽");
public static final Season WINTER = new Season("冬", "寒冷");
private Season(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {return name;}
public String getDesc() {return desc;}
@Override
public String toString() {
return "Season{" +
"name='" + name + ''' +
", desc='" + desc + ''' +
'}';
}
}
enum关键字实现枚举¶
enum Season {
- //参数名(实参列表)来定义枚举量
- //多个常量使用","来连接
- //如果使用无参构造器构建对象的话, 可以省略()
- //使用enum时应该将定义的常量写在前面
- //其余部分相同
SPRING("春", "温暖"), SUMMER("夏", "炎热"),
AUTUMN("秋", "凉爽"), WINTER("冬", "寒冷");
private String name;
private String desc; //描述
private Season(String name, String desc) {
this.name = name;
this.desc = desc;
}
public String getName() {return name;}
public String getDesc() {return desc;}
@Override
public String toString() {
return "Season{" +
"name='" + name + ''' +
", desc='" + desc + ''' +
'}';
}
}
-
使用enum关键字实现枚举的注意事项
-
使用enum关键字建立一个枚举类时, 默认会继承Enum类, 并且将自己定义为final类
-
可以将普通的
`public static final Season SPRING = new Season("春", "温暖");` 简化为`SPRING("春", "温暖");` 但必须知道调用的是哪个构造器
-
使用无参构造器创建枚举对象是,可以省略()和实参列表
-
多个枚举对象用","连接
-
枚举对象必须放在枚举类行首
-
-
enum类常用方法
说明:因为所有enum类隐式继承Enum类, 所以可以使用Enum类方法
protected Object | clone() 抛出 CloneNotSupportedException。 枚举类型不能被克隆 |
---|---|
int | compareTo(E o) 比较此枚举与指定对象的顺序。 |
boolean | equals(Object other) 当指定对象等于此枚举常量时,返回 true。 可以直接使用"=="来判断是否相等 |
protected void | finalize() 枚举类不能有 finalize 方法。 |
Class<E> | getDeclaringClass() 返回与此枚举常量的枚举类型相对应的 Class 对象。 用于判断两个枚举常量是否属于同一个枚举类型 |
int | hashCode() 返回枚举常量的哈希码。(覆盖Object的hashCode) |
String | name() 返回此枚举常量的名称,在其枚举声明中对其进行声明。 建议优先使用toString()方法 |
int | ordinal() 返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零(0,1,2,3….))。 |
String | toString() 返回枚举常量的名称,它包含在声明中。 可以重写 |
static |
valueOf(Class |
values:返回当前枚举类中的所有常量
来自 <https://itmyhome.com/java-api/java/lang/Enum.html>
-
enum实现接口
-
enum隐式继承Enum, 不能继承其他类(java只能单继承), 因此可以使用接口来完成功能
-
形式:与类相同
-
11.2注解¶
2022年6月14日
17:12
1. 什么是注解¶
-
jdk 5.0 新增的功能
-
注解(Annotation)也被称为元数据(Metadata), 用于修饰解释 包、类、方法、属性、构造器、局部变量等数据的信息, 这些信息被保存在Annotation的
name = value
对中。 -
Annotation的作用:
- 和注释一样, 注解不影响程序逻辑, 但注解可以被编译或者运行, 相当于嵌入代码中的补充信息
- 注解可以被其他程序(如:编译器等)读取
-
JavaSe中, 注解作用简单, 例如标记过时的功能, 忽略警告等
JavaEE中, 用于配置应用程序的任何切面, 代替JavaEE旧版中遗留的繁冗代码和XML配置等
-
Annotation'的格式:
- 注解是以"@注解名"在代码中存在的, 还可以添加一些参数值, 如:
@SuppressWarning(value = "unchecked")
- 注解是以"@注解名"在代码中存在的, 还可以添加一些参数值, 如:
-
Annotation在哪里使用:
- 可以附加在package, class, method, field等上面, 相当于为它们添加了额外的辅助信息, 我们可以通过反射机制实现对这些元数据的访问
-
框架 = 注解 + 反射机制 + 设计模式
2. 基本的Annotation介绍¶
-
@Override
: 限定某个方法是重写父类方法 (只能用于方法)-
编译器会检查方法是否真的重写了父类方法, 否则编译错误
-
如果不写@Override注解依然构成重写
-
@Override只能修饰方法
-
源码
-
-
@Deprecated
: 表示某个程序元素(类/方法)已过时-
表示不在推荐使用, 但是仍然可以使用
-
可以修饰方法, 类, 字段, 包, 参数等
-
@Deprecated可以作为版本升级过渡使用
-
源码
-
-
@SuppressWarnings
: 抑制编译器警告-
使用:
@SuppressWarnings({""})
内部写入希望抑制的警告信息关键字 用途 all 抑制所有警告 boxing 抑制装箱、拆箱操作时候的警告 cast 抑制映射相关的警告 dep-ann 抑制启用注释的警告 deprecation 抑制过期方法警告 fallthrough 抑制在 switch 中缺失 breaks 的警告 finally 抑制 finally 模块没有返回的警告 hiding 抑制相对于隐藏变量的局部变量的警告 incomplete-switch 忽略不完整的 switch 语句 nls 忽略非 nls 格式的字符 null 忽略对 null 的操作 rawtypes 使用 generics 时忽略没有指定相应的类型 restriction 抑制禁止使用劝阻或禁止引用的警告 serial 忽略在 serializable 类中没有声明 serialVersionUID 变量 static-access 抑制不正确的静态访问方式警告 synthetic-access 抑制子类没有按最优方法访问内部类的警告 unchecked 抑制没有进行类型检查操作的警告 unqualified-field-access 抑制没有权限访问的域的警告 unused 抑制没被使用过的代码的警告 -
作用范围与放置位置有关, 可以放置于具体的==语句, 方法, 类==
-
源码
@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(); }
-
3. 注解的使用示例¶
使用 Annotation时要在其前面增加 @
符号,并把该 Annotation当成个修饰符使用。用于修饰它支持的程序元素
例一:生成文档相关的注解¶
@author
标明开发该类模块的作者,多个作者之间使用,分割@version
标明该类模块的版本;@see
参考转向,也就是相关主题;@since
从哪个版本开始增加的;@param
对方法中某参数的说明,如果没有参数就不能写@return
对方法返回值的说明,如果方法的返回值类型是void
就不能写@exception
对方法可能抛出的异常进行说明,如果方法没有用throws
显式抛出的异常就不能写;- 其中
@param
、@return
和@exception
这三个标记都是只用于方法的。 @param
的格式要求:@param
形参名形参类型形参说明;@return
的格式要求:@return
返回值类型返回值说明;@exception
的格式要求:@exception
异常类型异常说明;@param
和@exception
可以并列多个;
代码示例:
/**
* @author bruce
* @project_name JavaSenior
* @package_name com.bruce.java
* @create 2020-04-26 10:58
*/
public class AnnotationTest {
/**
*程序的主方法
* @param args 传入命令行参数
*/
public static void main(String[] args) {
}
/**
* 求圆形面积
* @param radius 所求面积的半径
* @return 面积值
*/
public static double getArea(double radius){
return Math.PI * radius * radius;
}
}
例二:在编译时进行格式检查(JDK内置的基本注解)¶
@Override
: 限定重写父类方法, 该注解只能用于方法;@Deprecated
: 用于表示所修饰的元素(类, 方法等)已过时。通常是因为所修饰的结构危险或存在更好的择;@SuppressWarnings
: 抑制编译器警告;
代码示例:
public class AnnotationTest{
public static void mian (String [] args){
@SuppressWarning("unused")
int a = 0;
}
@Deprecated
public void print(){
System.out.print("过时的方法");
}
@Override
public String toString(){
return "重写的toString方法";
}
}
例三:跟踪代码依赖性,实现替代配置文件功能¶
在使用Spring框架时会大量用到注解驱动开发。
4. 如何自定义注解¶
参照 @SuppressWarnings
定义
- 注解声明为:
访问权限 @interface 注解名 {}
- 内部定义成员,通常使用value表示
- 可以指定成员的默认值,使用default定义
- 如果自定义注解没成员,表明是一个标识作用。
4.1 说明¶
- 如果注解有成员,在使用注解时,需要指明成员的值。
- 自定义注解必须配上注解的信息处理流程(使用反射)才意义。
- 自定义注解通过都会指明两个元注解:
@Retention
、@Target
4.2 代码举例:¶
@Inherited
@Repeatable(MyAnnotations.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE,TYPE_PARAMETER,TYPE_USE})
public @interface MyAnnotation {
String value() default "hello";
}
5. 元注解:¶
-
总述:
-
元注解: 用于修饰其他注解 (源码中使用) <仅了解>
-
分类
*
Retention
: 指定注解的作用范围,有三种SOURCE
,CLASS
,RUNTIME
*
Target
: 指定注解可以在哪些地方使用*
Documented
: 指定该注解是否会在javadoc 体现*
Inherited
: 子类会继承父类注解
-
-
@Retention
-
说明: 只能用于修饰一个Annotation 定义, 用于指定该Annotation 可以保留多长时间, @Rentention 包含一个RetentionPolicy类型的成员变量
-
使用@Rentention 时必须为该value 成员变量指定值:
@Retention 的三种值
1. RetentionPolicy.SOURCE: 编译器使用后,直接丢弃这种策略的注释
2. RetentionPolicy.CLASS: 编译器将把注解记录在class 文件中. 当运行Java 程序时, JVM 不会保留注解。这是默认值
3. RetentionPolicy.RUNTIME:编译器将把注解记录在class 文件中. 当运行Java 程序时, JVM 会保留注解. 程序可以通过反射获取该注解
-
源码
-
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
-
@Target
-
用于修饰Annotation定义, 用于指定被修饰的Annotation用于修饰那些程序元素
-
Target也包含一个value成员变量
-
源码:
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Target { /** * Returns an array of the kinds of elements an annotation type * can be applied to. * @return an array of the kinds of elements an annotation type * can be applied to */ ElementType[] value(); }
-
-
@Documented
-
用于指定被该元Annotation修饰的Annotation类将被javadoc工具提取成文档, 即在生成文档时, 可以看到该注解
-
源码
-
-
@Inherited
1. 被它修饰的Annotation将具有继承性, 如果某个类使用了被@Inherited修饰的Annotation, 则其子类将自动具有该注解 2. 说明: 实际应用中, 使用较少, 仅了解
6. 如何获取注解信息:¶
通过反射来进行获取、调用。
前提:要求此注解的元注解Retention中声明的生命周期状态为:RUNTIME.
7. JDK 8.0中注解的新特性:¶
可重复注解、类型注解
6.1 可重复注解:¶
① 在MyAnnotation上声明 @Repeatabl
e,成员值为 MyAnnotations.class
② MyAnnotation的Target和Retention等元注解与MyAnnotations相同。
6.2 类型注解:¶
ElementType.TYPE_PARAMETER
表示该注解能写在类型变量的声明语句中(如:泛型声明。)
ElementType.TYPE_USE
表示该注解能写在使用类型的任何语句中。