欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 手游 > JAVA篇06 —— enumAnnotation

JAVA篇06 —— enumAnnotation

2024/11/29 6:45:45 来源:https://blog.csdn.net/nyxdsb/article/details/144093527  浏览:    关键词:JAVA篇06 —— enumAnnotation

 欢迎来到我的主页:【一只认真写代码的程序猿

本篇文章收录于专栏【小小爪哇

如果这篇文章对你有帮助,希望点赞收藏加关注啦~

目录

1 自定义实现枚举

2 关键字enum

3 values() ordinal() valueOf()

4 enum常用方法示例

5 enum实现接口

6 注解

6.1 @Override

6.2 @Deprecated

6.3 @SuppressWarnings

7 元注解

7.1 @Retention

7.2 @Target

7.3 @Documented

7.4 @Inherited


设计一个季节类,需要去分别new四次很麻烦。我们发现:季节的值是有限的几个值(spring, summer, autumn, winter)并且是只读,不需要修改。枚举属于一种特殊的类, 里面只包含一组有限的特定的对象。

  1. 不需要提供setXxx 方法,因为枚举对象值通常为只读。
  2. 对枚举对象/属性使用 final + static 共同修饰,实现底层优化。
  3. 枚举对象名通常使用全部大写,常量的命名规范。
  4. 枚举对象根据需要,也可以有多个属性 。

1 自定义实现枚举

1) 构造器私有化

2) 本类内部创建一组对象[四个 春夏秋冬]

3) 对外暴露对象(通过为对象添加 public final static 修饰符)

4) 可以提供 get 方法, 但是不要提供 set

package Enumeration;/*** @ClassName Season* @Description* @Date 2024/11/27 20:17* @Version V1.0*/
public class Season {public static void main(String[] args) {System.out.println(Seasons.AUTUMN);System.out.println(Seasons.SPRING);}
}class Seasons {//类//定义了四个对象, 固定.public static final Seasons SPRING = new Seasons("春天", "温暖");public static final Seasons WINTER = new Seasons("冬天", "寒冷");public static final Seasons AUTUMN = new Seasons("秋天", "凉爽");public static final Seasons SUMMER = new Seasons("夏天", "炎热");private String name;private String desc;//描述//1. 将构造器私有化,目的防止 直接 new//2. 去掉 setXxx 方法, 防止属性被修改//3. 在 Season 内部, 直接创建固定的对象//4. 优化, 可以加入 final 修饰符private Seasons(String name, String desc) {this.name = name;this.desc = desc;}public String getName() {return name;}public String getDesc() {return desc;}@Overridepublic String toString() {return "Season{" +"name='" + name + '\'' +", desc='" + desc + '\'' +'}';}
}

2 关键字enum

package Enumeration;/*** @ClassName Season* @Description* @Author 聂宇旋* @Date 2024/11/27 20:17* @Version V1.0*/
public class Season {public static void main(String[] args) {System.out.println(Seasons2.AUTUMN);System.out.println(Seasons2.SPRING);}
}enum Seasons2{SPRING("春天", "温暖"),WINTER("冬天", "寒冷"),AUTUMN("秋天", "凉爽"),SUMMER("夏天", "炎热"),;private String name;private String dec;private Seasons2(){}private Seasons2(String name,String dec){this.name = name;this.dec=dec;}public String getName() {return name;}public String getDec() {return dec;}@Overridepublic String toString() {return "Season{"+"name="+name+"description="+dec+"}";}
}

3 values() ordinal() valueOf()

enum 定义的枚举类默认继承了 java.lang.Enum 类,并实现了 java.lang.Serializable 和 java.lang.Comparable 两个接口。

values(), ordinal() 和 valueOf() 方法位于 java.lang.Enum 类中:

  • values() 返回枚举类中所有的值。
  • ordinal()方法可以找到每个枚举常量的索引,就像数组索引一样。
  • valueOf()方法返回指定字符串值的枚举常量.
  • 当我们使用 enum 关键字开发一个枚举类时, 默认会继承 Enum 类, 而且是一个 final 类。
  • 传统的 public static final Season2 SPRING = new Season2("春天", "温暖"); 简化成 SPRING("春天", "温暖")。
  • 如果使用无参构造器 创建 枚举对象, 则实参列表和小括号都可以省略(代码如下)
enum Color{ RED, GREEN, BLUE; 
} 
public class Test{ public static void main(String[] args){ // 调用 values() Color[] arr = Color.values(); // 迭代枚举for (Color col : arr) { // 查看索引System.out.println(col + " at index " + col.ordinal()); } // 使用 valueOf() 返回枚举常量,不存在的会报错 IllegalArgumentException System.out.println(Color.valueOf("RED")); // System.out.println(Color.valueOf("WHITE")); } 
}

4 enum常用方法示例

正如前面所说,enum会隐式继承Enum。

public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable {
}
  1. toString:Enum 类已经重写过了, 返回的是当前对象名,子类可以重写该方法, 用于返回对象的属性信息
  2. name: 返回当前对象名(常量名) , 子类中不能重写
  3. ordinal: 返回当前对象的位置号, 默认从 0 开始 
  4. values: 返回当前枚举类中所有的常量
  5. valueOf: 将字符串转换成枚举对象, 要求字符串必须为已有的常量名, 否则报异常
  6. compareTo: 比较两个枚举常量, 比较的就是编号
package Enumeration;enum Seasons2 {SPRING("春天", "温暖"),WINTER("冬天", "寒冷"),AUTUMN("秋天", "凉爽"),SUMMER("夏天", "炎热"),;private String name;private String dec;private Seasons2() {}private Seasons2(String name, String dec) {this.name = name;this.dec = dec;}public String getName() {return name;}public String getDec() {return dec;}@Overridepublic String toString() {return "Season{" +"name=" + name+ "description=" + dec+ "}";}
}/*** @ClassName Season* @Description* @Author 聂宇旋* @Date 2024/11/27 20:17* @Version V1.0*/
public class Season {public static void main(String[] args) {Seasons2 winter = Seasons2.WINTER;System.out.println(winter.name());//输出名字WINTERSystem.out.println(winter.ordinal());//输出下标,与数组类似,输出1Seasons2[] values = Seasons2.values();//获取所有值,放入values数组for (Seasons2 season : values) {//增强for来遍历输出System.out.println(season);}Seasons2 autumn1 = Seasons2.AUTUMN;Seasons2 autumn = Seasons2.valueOf("AUTUMN");//根据字符串查找,且String必须在枚举中否则报错System.out.println("autumn=" + autumn);System.out.println(autumn);System.out.println(autumn == autumn1);//True}
}

5 enum实现接口

package Enumeration;/*** @ClassName enumImpl* @Description 枚举类实现接口* @Date 2024/11/28 9:08* @Version V1.0*/
public class enumImpl {public static void main(String[] args) {Music.CLASSICMUSIC.play();}
}
interface IPlay{void play();
}
enum Music implements IPlay{CLASSICMUSIC,POPMUSIC,;@Overridepublic void play() {System.out.println("音乐...");}
}

6 注解

  1. 注解(Annotation)也被称为元数据(Metadata), 用于修饰解释 包、 类、 方法、 属性、 构造器、 局部变量等数据信息。
  2. 和注释一样, 注解不影响程序逻辑, 但注解可以被编译或运行, 相当于嵌入在代码中的补充信息。
  3. 在 JavaSE 中, 注解的使用目的比较简单, 例如标记过时的功能, 忽略警告等。 在 JavaEE 中注解占据了更重要的角色, 例如用来配置应用程序的任何切面, 代替 java EE 旧版中所遗留的繁冗代码和 XML 配置等。

6.1 @Override

@Interface表示一个“注解类”,只能重写方法(Target里是METHOD),并且会检查是否真的重写了,如果没有重写则报错。Target是修饰注解的注解,称为“元注解”。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

6.2 @Deprecated

用于表示某个程序元素(类, 方法等)已过时。可以做版本升级过渡使用。如果继续使用的话编译器会warning来提醒。

package Enumeration;/*** @ClassName DeprecatedTest* @Description @Deprecated注解的使用* 1. @Deprecated 修饰某个元素, 表示该元素已经过时* 2. 即不在推荐使用, 但是仍然可以使用* 3. 查看 @Deprecated 注解类的源码* 4. 可以修饰方法, 类, 字段, 包, 参数 等等* 5. @Deprecated 可以做版本升级过渡使用* @Date 2024/11/28 9:18* @Version V1.0*//*@Documented@Retention(RetentionPolicy.RUNTIME)@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})public @interface Deprecated {}
*/public class DeprecatedTest {public static void main(String[] args) {A a = new A();a.hi();System.out.println(a.n1);}
}@Deprecated
class A {@Deprecatedpublic int n1 = 10;@Deprecatedpublic void hi() {}
}

6.3 @SuppressWarnings

不用背,IDE中可以看提示,做产品迭代使用的注解。

package Enumeration;import java.util.ArrayList;
import java.util.List;/*** @ClassName SuppressWarnings_* @Description 当我们不希望看到这些警告的时候, 可以使用 SuppressWarnings 注解来抑制警告信息* 在{""} 中, 可以写入你希望抑制(不显示)警告信息* 可以指定的警告类型有* 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, 抑制与未用的程式码及停用的程式码相关的警告* @Author 聂宇旋* @Date 20241128 9:25* @Version V1.0*/// 关于 SuppressWarnings 作用范围是和你放置的位置相关
// 比如 @SuppressWarnings 放置在 main 方法, 那么抑制警告的范围就是 main
// 通常我们可以放置具体的语句, 方法, 类
//(1) 放置的位置就是 TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE
//(2) 该注解类有数组 String[] values() 设置一个数组比如 {"rawtypes", "unchecked", "unused"}
@SuppressWarnings({"rawtypes", "unchecked", "unused"})
public class SuppressWarnings_ {public static void main(String[] args) {List list = new ArrayList();list.add("jack");list.add("tom");list.add("mary");int i;System.out.println(list.get(1));}public void f1() {@SuppressWarnings({"rawtypes"})List list = new ArrayList();list.add("jack");list.add("tom");list.add("mary");@SuppressWarnings({"unused"})int i;System.out.println(list.get(1));}
}
/*
源码如下:
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {String[] value();
}*/

7 元注解

使用不多,了解即可,方便看源码的时候知道他在干啥。

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

7.1 @Retention

只能用于修饰一个 Annotation 定义, 用于指定该 Annotation 可以保留多长时间 @Rentention 包含一个 RetentionPolicy类型的成员变量, 使用 @Rentention 时必须为该 value 成员变量指定值。

@Retention 的三种值:

  1. RetentionPolicy.SOURCE: 编译器使用后, 直接丢弃这种策略的注
  2. RetentionPolicy.CLASS: 编译器将把注解记录在 class 文件中. 当运行 Java 程序时, JVM 不会保留注解。 这是默认值。
  3. RetentionPolicy.RUNTIME:编译器将把注解记录在 class 文件中. 当运行 Java 程序时, JVM 会保留注解. 程序可以通过反射获取该注解
  4. 案例:Override中用了
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}//解释:Override的作用域在SOURCE,即编译时生效,不会写入到class文件
//也不会在Runtime时生效

7.2 @Target

用于修饰 Annotation 定义, 用于指定被修饰的 Annotation 能用于修饰哪些程序元素,@Target 也包含一个名为 value 的成员变量。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
//可以修饰方法, 类, 字段, 包, 参数 等等
public @interface Deprecated {
}

Target源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)//作用范围是Runtime
@Target(ElementType.ANNOTATION_TYPE)//AnnotationType就说明Target只能修饰注解
public @interface Target {//说明它是注解/*** Returns an array of the kinds of elements an annotation interface* can be applied to.* @return an array of the kinds of elements an annotation interface* can be applied to*/ElementType[] value();//看elementType的取值
}

7.3 @Documented

生成文档用的,被Document注解的注解,在javadoc提取成文档后,在文档中可以看到这个注解。

所以,定义为Document的注解必须把Retention设置为Runtime。举例如下:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
//可以修饰方法, 类, 字段, 包, 参数 等等
public @interface Deprecated {
}

Document源码(注释由GPT生成):

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
/*
1. `@Documented`:这是一个元注解(meta-annotation)
意味着它被用来注解其他注解。`@Documented` 注解本身被
用来指示被它标记的注解应该被 javadoc 工具包含在生成的文档中。2. `@Retention(RetentionPolicy.RUNTIME)`:这是另一个元注解,
`@Retention` 指定了注解的保留策略。`RetentionPolicy.RUNTIME` 
表示这个注解应该在运行时保留,这意味着它可以通过反射(Reflection)被检测到。3. `@Target(ElementType.ANNOTATION_TYPE)`:这是第三个元注解,
`@Target` 指定了注解可以应用的Java元素类型。
`ElementType.ANNOTATION_TYPE` 表示这个注解只能用于其他注解类型。4. `public @interface Documented { }`:这是定义注解的声明。
`@interface` 是用来声明注解的关键字。`Documented` 是注解的名称,
它是一个公共接口,这意味着它可以被任何其他类或接口使用。总结来说,`Documented` 注解是一个标记,用于指示其他注解应该被
包含在javadoc生成的文档中,并且这个注解在运行时是可用的,只能
用于其他注解类型。这是一个常用的注解,因为它允许开发者控制哪些
注解信息会显示在API文档中。
*/

7.4 @Inherited

被它修饰的Annotation具有继承性;如果类A使用了被Inherittd修饰的Annotation,则其子类B自动具有该注解。(有什么用呢qwq...)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com