news 2026/7/4 4:15:07

Java基础快速入门:枚举与注解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java基础快速入门:枚举与注解

本文纲要

一、枚举

  1. 为什么需要枚举
  2. 枚举的定义格式
  3. 枚举的特点
  4. 枚举的常用方法

二、注解

  1. 注解的优势
  2. 注解概述与Java内置注解
  3. 自定义注解
  4. 特殊属性value
  5. 自定义注解练习
  6. 元注解

枚举

1 ) 为什么需要枚举

在程序中经常需要表示一组固定的值,例如四季(春、夏、秋、冬)。早期我们可能会这样实现:

publicclassSeason{publicstaticfinalintSPRING=1;publicstaticfinalintSUMMER=2;publicstaticfinalintAUTUMN=3;publicstaticfinalintWINTER=4;}

这种设计存在明显缺陷:

  • 代码不够简洁,需要定义多个常量。
  • 仅通过常量名称区分不同的值,类型安全性差。
  • 可能出现无意义的运算(例如SPRING + SUMMER),编译器不会报错。

为了更简洁、安全地表示固定的值集合,Java 提供了枚举。

2 ) 枚举的定义格式

枚举使用enum关键字定义,格式与类相似。
枚举项之间用逗号分隔,最后一个枚举项后可以加分号。

语法格式:

publicenum枚举名{枚举项1,枚举项2,...;}

示例:

// Season.javapublicenumSeason{SPRING,SUMMER,AUTUMN,WINTER;}

3 ) 枚举的特点

枚举的本质是一个特殊的类,具备以下特点:

特点说明
1. 所有枚举类都是Enum的子类Enum是所有枚举类型的公共基类,枚举类自动继承Enum
2. 通过“枚举类名.枚举项名称”访问枚举项例如Season.SPRING
3. 每个枚举项都是该枚举类的对象Season.SPRING的类型就是Season
4. 枚举类可以定义成员变量可以在枚举中声明属性。
5. 第一行必须是枚举项,分号可省略(但建议保留)若枚举类中还有其他内容(如成员变量、方法),分号不能省略。
6. 可以有构造方法,但必须是private(默认也是private枚举项会隐式调用构造方法,如果未指定,默认调用无参构造。
7. 可以有抽象方法,但每个枚举项必须重写该方法枚举项后面需要跟大括号实现抽象方法。

演示代码:

// Season.javapublicenumSeason{SPRING("春"){@Overridepublicvoidshow(){System.out.println(this.name);}},SUMMER("夏"){@Overridepublicvoidshow(){System.out.println(this.name);}},AUTUMN("秋"){@Overridepublicvoidshow(){System.out.println(this.name);}},WINTER("冬"){@Overridepublicvoidshow(){System.out.println(this.name);}};publicStringname;// 有参构造(private 可省略,默认 private)privateSeason(Stringname){this.name=name;}// 抽象方法publicabstractvoidshow();}
// EnumDemo.javapublicclassEnumDemo{publicstaticvoidmain(String[]args){// 特点2:通过枚举类名访问枚举项System.out.println(Season.SPRING);System.out.println(Season.SUMMER);System.out.println(Season.AUTUMN);System.out.println(Season.WINTER);// 特点3:每个枚举项都是该枚举类的对象Seasonspring=Season.SPRING;}}

特点详解:

  • 如果枚举类中定义了带参构造,枚举项后必须传入参数,例如SPRING("春")
  • 如果枚举类中存在抽象方法,每个枚举项都必须以匿名内部类形式重写该方法。
  • 枚举项必须位于第一行,其上的注释、空格不影响,但不能有其他语句。

4 ) 枚举的常用方法

枚举类继承自Enum,因此可以直接使用以下方法:

方法说明
String name()获取枚举项的名称。
int ordinal()返回枚举项在枚举类中的索引(从0开始)。
int compareTo(E o)比较两个枚举项,返回索引差值。
String toString()返回枚举项的名称(与name()类似,主要用于输出)。
static <T> T valueOf(Class<T> type, String name)根据枚举类和名称获取对应的枚举项。
static E[] values()获取所有枚举项,返回数组。

示例:

// Season.javapublicenumSeason{SPRING,SUMMER,AUTUMN,WINTER;}// EnumDemo.javapublicclassEnumDemo{publicstaticvoidmain(String[]args){// name()Stringname=Season.SPRING.name();System.out.println(name);// SPRINGSystem.out.println("-----------------------------");// ordinal()intindex1=Season.SPRING.ordinal();intindex2=Season.SUMMER.ordinal();intindex3=Season.AUTUMN.ordinal();intindex4=Season.WINTER.ordinal();System.out.println(index1);// 0System.out.println(index2);// 1System.out.println(index3);// 2System.out.println(index4);// 3System.out.println("-----------------------------");// compareTo()intresult=Season.SPRING.compareTo(Season.WINTER);System.out.println(result);// -3 (0 - 3)System.out.println("-----------------------------");// toString()Strings=Season.SPRING.toString();System.out.println(s);// SPRINGSystem.out.println("-----------------------------");// valueOf()Seasonspring=Enum.valueOf(Season.class,"SPRING");System.out.println(spring);System.out.println(Season.SPRING==spring);// trueSystem.out.println("-----------------------------");// values()Season[]values=Season.values();for(Seasonvalue:values){System.out.println(value);}}}

注意:toString()虽然也能返回名称,但一般直接使用name()toString()的存在意义在于打印枚举项时自动调用,输出名称而非地址值。

注解

1 ) 注解的优势

在传统的 Servlet 配置中,我们通常使用 XML 文件,例如web.xml

<servlet><servlet-name>MyServlet</servlet-name><servlet-class>com.example.MyServlet</servlet-class></servlet><servlet-mapping><servlet-name>MyServlet</servlet-name><url-pattern>/my</url-pattern></servlet-mapping>

XML 虽然增强了可读性,但配置过多时文件会变得臃肿。
注解的出现简化了配置,可以直接在类上声明:

@WebServlet("/my")publicclassMyServletextendsHttpServlet{...}

优点:简洁、直观、零配置。

2 ) 注解概述与Java内置注解

注解(Annotation)是对程序进行标注和解释的元数据,主要用于给编译器或虚拟机提供信息。

常见内置注解:

注解作用
@Override标注方法为重写父类的方法,编译器会检查重写是否正确。
@Deprecated表示方法已过时,不推荐使用。
@SuppressWarnings压制警告,可作用于方法或类。

示例代码:

// Fu.javapublicclassFu{publicvoidshow(){System.out.println("父类的方法");}}// Zi.java@SuppressWarnings(value="all")// 压制本类中所有警告publicclassZiextendsFu{@Overridepublicvoidshow(){System.out.println("子类的方法");}@Deprecatedpublicvoidmethod(){System.out.println("method.......");}publicvoidfunction2(){inta=10;}@SuppressWarnings(value="all")// 压制本方法中所有警告publicvoidfunction(){inta=10;intb=20;// 未使用的变量默认会显示灰色警告,加上注解后警告消失}}

注解与注释的区别:

  • 注释:给程序员看的,解释代码逻辑。
  • 注解:给编译器/虚拟机看的,携带程序的特殊功能。

3 ) 自定义注解

自定义注解使用@interface关键字,格式如下:

public@interface注解名{public类型 属性名()default默认值;}

属性类型支持:

  • 基本数据类型(intfloat等)
  • String
  • Class
  • 注解
  • 枚举
  • 以上类型的一维数组

示例:定义并使用自定义注解

项目结构:

myannotation/src/com/wb/myanno2/ ├── Anno1.java ├── Anno2.java ├── AnnoDemo.java └── Season.java
// Season.java(枚举,用于注解属性类型)publicenumSeason{SPRING,SUMMER,AUTUMN,WINTER;}// Anno2.java(另一个注解,用于嵌套)public@interfaceAnno2{}// Anno1.java(自定义注解)public@interfaceAnno1{// 基本类型inta()default23;// String类型publicStringname()default"itheima";// Class类型publicClassclazz()defaultAnno2.class;// 注解类型publicAnno2anno()default@Anno2;// 枚举类型publicSeasonseason()defaultSeason.SPRING;// int数组publicint[]arr()default{1,2,3,4,5};// 枚举数组publicSeason[]seasons()default{Season.SPRING,Season.SUMMER};// 特殊属性 valuepublicStringvalue();}// AnnoDemo.java(使用注解)// 如果注解中有属性没有默认值,使用时必须赋值// @Anno1(name = "itheima") // 完整写法@Anno1("abc")// 如果只给 value 赋值,可以省略 "value="publicclassAnnoDemo{}

使用规则:

  • 如果注解的属性未指定默认值,使用时必须显式赋值。
  • 赋值的格式:属性名 = 值,多个属性用逗号分隔。

4 ) 特殊属性 value

当注解中定义了名为value的属性,且在使用时只给该属性赋值,则可以省略value=,直接写值。

示例:

public@interfaceAnno1{publicStringvalue();}@Anno1("hello")// 等价于 @Anno1(value = "hello")publicclassTest{}

5 ) 自定义注解练习

需求:自定义一个@Test注解,将其标注在方法上。程序运行时,自动执行所有标注了@Test的方法。

实现步骤:

  1. 定义@Test注解,并指定其保留策略为RUNTIME(运行时可见)。
  2. 在目标类UseTest的某些方法上添加@Test
  3. 通过反射获取UseTest的所有方法,检查是否标注了@Test,如果是则执行。

项目结构:

myannotation/src/com/wb/myanno3/ ├── Test.java ├── UseTest.java └── AnnoDemo.java
// Test.javaimportjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;@Retention(value=RetentionPolicy.RUNTIME)// 保留到运行时public@interfaceTest{}// UseTest.javapublicclassUseTest{publicvoidshow(){System.out.println("UseTest....show....");}@Testpublicvoidmethod(){System.out.println("UseTest....method....");}@Testpublicvoidfunction(){System.out.println("UseTest....function....");}}// AnnoDemo.javaimportjava.lang.reflect.InvocationTargetException;importjava.lang.reflect.Method;publicclassAnnoDemo{publicstaticvoidmain(String[]args)throwsException{// 1. 获取 UseTest 类的字节码对象Class<?>clazz=Class.forName("com.wb.myanno3.UseTest");// 2. 创建对象(用于后续调用方法)UseTestuseTest=(UseTest)clazz.newInstance();// 3. 获取所有方法Method[]methods=clazz.getDeclaredMethods();// 4. 遍历方法,检查是否有 @Test 注解for(Methodmethod:methods){// isAnnotationPresent:判断是否存在指定注解if(method.isAnnotationPresent(Test.class)){method.invoke(useTest);// 执行方法}}}}

运行结果:

UseTest....method.... UseTest....function....

关键点:注解必须声明@Retention(RetentionPolicy.RUNTIME),否则在运行时无法通过反射读取。

6 ) 元注解

元注解是描述注解的注解,JDK 提供了四个常用元注解:

元注解作用
@Target指定注解能使用的位置(类、方法、成员变量等)。
@Retention指定注解的生命周期(源码、字节码、运行时)。
@Inherited表示注解可以被子类继承。
@Documented表示注解会出现在 API 文档中。

示例:

// Anno.javaimportjava.lang.annotation.*;@Target({ElementType.FIELD,ElementType.TYPE,ElementType.METHOD})// 可作用在成员变量、类、方法上@Retention(RetentionPolicy.RUNTIME)// 保留到运行时//@Inherited // 打开则允许子类继承该注解public@interfaceAnno{}// Person.java(父类)@AnnopublicclassPerson{}// Student.java(子类)publicclassStudentextendsPerson{publicvoidshow(){System.out.println("student.......show..........");}}// StudentDemo.java(测试继承)publicclassStudentDemo{publicstaticvoidmain(String[]args)throwsClassNotFoundException{Class<?>clazz=Class.forName("com.wb.myanno4.Student");booleanresult=clazz.isAnnotationPresent(Anno.class);System.out.println(result);// 若 @Inherited 生效则为 true,否则 false}}

说明:

  • @Target取值ElementType.FIELD(字段)、TYPE(类/接口)、METHOD(方法)等。
  • @Retention取值RetentionPolicy.SOURCE(源码阶段丢弃)、CLASS(保留到字节码,默认)、RUNTIME(保留到运行时,可通过反射获取)。
  • @Inherited仅对类上的注解有效,方法、字段上的注解无法继承。

总结

本文系统介绍了 Java 中枚举和注解的核心概念、使用方式及常见场景,适合初学者快速入门。掌握这些基础知识后,可以更好地理解框架中的配置和元数据机制。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/4 4:14:23

我用了十年终端,今天才真正学会使用它

上个月&#xff0c;我看到一位资深开发者在90秒内修复了一个线上的问题&#xff0c;让我深受震撼。因为他没有谷歌搜索&#xff0c;没有翻看小抄&#xff0c;只是流畅地在终端里敲击&#xff0c;就像在进行一场对话。我原以为他有什么秘密武器&#xff0c;结果没有。跟他交流玩…

作者头像 李华
网站建设 2026/7/4 4:13:22

TVA对具身智能领域的核心技术支撑(16)

前沿技术介绍&#xff1a;AI智能体视觉&#xff08;TVA&#xff0c;Transformer-based Vision Agent&#xff09;是依托Transformer架构与“因式智能体”理论所构建的颠覆性工业视觉技术&#xff0c;属于“物理AI” 领域的一种全新技术形态&#xff0c;完成了从“虚拟世界”到“…

作者头像 李华
网站建设 2026/7/4 4:12:06

永磁同步电机无位置传感器控制:旋转高频注入法详解

1. 旋转高频注入法原理揭秘永磁同步电机无位置传感器控制一直是行业内的技术难点&#xff0c;而旋转高频注入法就像给电机装上了"声纳系统"。这个方法的核心思想是通过注入特定高频信号&#xff0c;利用电机自身的物理特性来反推转子位置&#xff0c;完全不需要传统的…

作者头像 李华
网站建设 2026/7/4 4:10:31

C++数学-数论筛质数经典OJ题流食般投喂

先做题自己思考&#xff0c;再看解析呦~OJ题来源&#xff1a;洛谷OJ题名&#xff1a;素数密度OJ题归属&#xff1a;数学-数论【筛质数】解题算法&#xff1a;线性筛、埃氏筛&#x1f43b;算法原理&#xff1a;&#x1f43b;借助素数的判定中用试除法从 [1&#xff0c;sqrt r] 进…

作者头像 李华
网站建设 2026/7/4 4:06:12

【MATLAB例程】二维平面下,多目标定位,采用4个基站的AOA+测距辅助定位,MATLAB代码。付完整可运行的m文件下载链接

原创程序,请勿翻卖 文章目录 程序简介 程序功能 误差评价指标解释 运行结果 MATLAB源代码 相关方向 程序简介 程序功能 本代码实现了基于到达角度(AOA, Angle of Arrival) 的二维平面多目标定位,测距信息作为辅助增强手段。程序在 4 个基站、8 个目标的场景下对比两种方案…

作者头像 李华
网站建设 2026/7/4 4:05:44

图论在社交网络分析中的3个核心应用:从理论到NetworkX实战

图论在社交网络分析中的3个核心应用&#xff1a;从理论到NetworkX实战社交网络已经成为现代社会中不可或缺的一部分&#xff0c;从Facebook的好友关系到Twitter的关注网络&#xff0c;再到LinkedIn的职业连接&#xff0c;这些平台都构建在复杂的网络结构之上。理解这些网络的结…

作者头像 李华