第九节注解和枚举

第二十二章注解

1. 注解概述

Java注解又称Java标注,是在 JDK5 时引入的新特性,注解(也被称为元数据)。

Java注解它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联。

Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。

2. 生成文档

生成帮助文档@author和@version

  • @author:用来标识作者姓名。
  • @version:用于标识对象的版本号,适用范围:文件、类、方法。
  • @Data:创建的时间
  • @Description:描述

示例:

使用**@author和@version注解就是告诉Javadoc工具**在生成帮助文档时把作者姓名和版本号也标记在文档中。

使用javadoc工具生成帮助文档:

javadoc -encoding utf-8 -author -version demo.java

D:\Power\javase\24-注解\src\注解>javadoc -encoding utf-8 -author -version demo.java

要和生成文档的java在同一目录下

3. 注解分类

3.1 JDK自带的标准注解

注解名称功能描述
@Overried检查该方法是否是重写方法,如果发现其父类,或者是引用的接口并没有该方法时,会编译报错
@Deprecated标记过时方法,如果使用该方法,会编译警告
@SupperssWarning指示编译器去忽略注释中声明的警告
@Functionallnterfacejava8支持,标志是一个匿名的函数式接口
3.1.1 @Override

如果试图使用 @Override 标记一个实际上并没有覆写父类的方法时,java 编译器会告警。

/**
 * @author 小宋学java
 * @version 1.0
 * @Data 2022/12/6 14:22
 * @Description TODO
 */
public class Demo01 {
    public void methodFu(){
        System.out.println("methodFu()");
    }

}
class Zi extends Demo01{

    // 重写父的方法
    @Override
    public void methodFu() {
        System.out.println("Zi()");
    }
} 

3.1.2 @Deprecated
/**
 * @author 小宋学java
 * @version 1.0
 * @Data 2022/12/6 14:25
 * @Description TODO
 */
@Deprecated //用于标明被修饰的类或类成员、类方法已经废弃、过时,不建议使用。
public class Demo02 {
    @Deprecated
    private String name;

    @Deprecated
    public Demo02(String name) {
        this.name = name;
    }
}
3.1.3 @SuppressWarnings

@SuppressWarnings 用于关闭对类、方法、成员编译时产生的特定警告。

@SuppressWarnings 注解的常见参数值的简单说明:

参数作用
deprecation关闭了使用了不赞成使用的类或者方法时的警告
unchecked执行了未检查的转换时的警告,例如当使用集合时没有泛型来指定集合报错的类型
fallthrough当Switch程序块直接通往下一种情况而没有Break时的警告
path在类路径、源文件路径中有不存在的路径时的警告
serial当在可序列化的类上缺少了serialVersionUUID时的警告
finally任何finally子句不能正常完成时的警告
all所有警告
抑制单类型的警告

@SuppressWarnings("unchecked")  
public void addItems(String item){  
  @SuppressWarnings("rawtypes")  
   List items = new ArrayList();  
   items.add(item);  
}

抑制多类型的警告

@SuppressWarnings(value={"unchecked", "rawtypes"})  
public void addItems(String item){  
   List items = new ArrayList();  
   items.add(item);  
}


抑制所有类型的警告

@SuppressWarnings("all")  
public void addItems(String item){  
   List items = new ArrayList();  
   items.add(item);  
}

3.2 元注解

元注解是java API提供的,是用于修饰注解的注解,通常用在注解的定义上:

元注解名称功能描述
@Retention标识这个注解是只在代码中,还是编入类文件中,或者是在运行时可以通过反射访问
@Documented标识这些注解是否包含在用户文档中
@Target标识这个注解的作用范围
@lnherited标识注解可被继承类获取
@Repeatable标识某注解可以在同一个声明上使用多次
3.2.1 @Retention

@Retention用来定义该注解在哪一个级别可用,在源代码中(SOURCE)、类文件中(CLASS)或者运行时(RUNTIME)。

@Retention 源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    /**
     * Returns the retention policy.
     * @return the retention policy
     */
    RetentionPolicy value();
}

etentionPolicy 是一个枚举类型,它定义了被 @Retention 修饰的注解所支持的保留级别:

public enum RetentionPolicy {
    //此注解类型的信息只会记录在源文件中,编译时将被编译器丢弃,也就是说
   //不会保存在编译好的类信息中
    SOURCE,

    //编译器将注解记录在类文件中,但不会加载到JVM中。如果一个注解声明没指定范围,则系统
    //默认值就是Class
    CLASS,

    //注解信息会保留在源文件、类文件中,在执行的时也加载到Java的JVM中,因此可以反射性的读取。
    RUNTIME
}
3.2.2 @Documented

@Documented:生成文档信息的时候保留注解,对类作辅助说明

3.2.3 @Target

@Target:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)

@Target源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    ElementType[] value();
}

ElementType 是一个枚举类型,它定义了被 @Target 修饰的注解可以应用的范围:

public enum ElementType {
    // 应用于类、接口(包括注解类型)、枚举  ElementType.TYPE
    TYPE,

	// 用于字段或者属性 ElementType.FIELE
    FIELD,

	// 用于方法 ElementType.MEHTOD
    METHOD,

    // 用于方法的参数
    PARAMETER,

    // 用构造方法
    CONSTRUCTOR,

    // 用于局部变量
    LOCAL_VARIABLE,


    // 用于包
    PACKAGE,

    // 1.8新增 用于类型变量
    TYPE_PARAMETER,

    // 1.8新增 用于任何使用类型的语句中
    TYPE_USE,

    
}

3.2.4 @Inherited

@Inherited:说明子类可以继承父类中的该注解

表示自动继承注解类型。 如果注解类型声明中存在 @Inherited 元注解,则注解所修饰类的所有子类都将会继承此注解。

3.2.5 @Repeatable

@Repeatable 表示注解可以重复使用。

当我们需要重复使用某个注解时,希望利用相同的注解来表现所有的形式时,我们可以借助@Repeatable注解。

3.3 自定义注解

3.3.1 定义注解格式
public @interface 注解名{

}
如:定义一个名为Book的注解
public @interface Book {
	字段类型 字段名1();
    字段类型 字段名2();
} 

3.3.2 字段类型的格式

属性的格式

  • 格式1:数据类型 属性名();
  • 格式2:数据类型 属性名() default 默认值;
public @interface Book {
  String name(); // 书名
  String author() ; // 作者
  Double price() default 20.8; // 价格
} 

tips:注解字段类型可以有如下:

  • 八种基本数据类型(int,float,boolean,byte,double,char,long,short)
  • String类型,Class类型,枚举类型,注解类型
  • 以上所有类型的一维数组
3.3.3 自定义注解

定义一个注解:Book

  • 包含属性:String value() 书名
  • 包含属性:double price() 价格,默认值为 100
  • 包含属性:String[] authors() 多位作者

示例代码:

// 可以出现在方法上 类上 字段上
@Target({ElementType.METHOD,ElementType.TYPE,ElementType.FIELD})
public @interface Book {
    String value();
    double price() default 100.0;
    String[] authors();
}


使用注解

public class BookShelf {
    @Book(value = "《汉书》",price = 108,authors = {"班固","班昭"})
    public void showBook(){
		
    }
}

注意事项:

  • 如果属性有默认值,则使用注解的时候,这个属性可以不用赋值。

  • 如果属性没有默认值,那么在使用注解时一定要给属性赋值。

3.3.4 特殊属性value

当注解中只有一个属性且名称是value,在使用注解时给value属性赋值可以直接给属性值,无论value是单值元素还是数组类型。

定义一个注解:

// 定义注解Book
public @interface Book {
	// 书名
	String value();
}

使用注解:

// 使用注解Book
public class BookShelf {
    @Book("《史记》")
    public void showBook(){

    }
}

或者:

public class BookShelf {
    @Book(value="《史记》")
    public void showBook(){

    }
}

如果注解中除了value属性还有其他属性,且至少有一个属性没有默认值,则在使用注解给属性赋值时,value属性名不能省略。

当注解中除了value还有其他属性时,在赋值时必须指定全部的属性名,value属性名不能省略。

第二十五章枚举

1.枚举概述

枚举(enum),全称enumeration是JDK 1.5 中引入的新特性。Java 枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等。

在JDK1.5 之前,我们定义常量都是: public static fianl。有了枚举之后,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法。

2.定义枚举类型

2.1 静态常量案例

我们使用静态常量来设置一个季节类:

public class Season {
    public static final Integer SPRING = 1;
    public static final Integer SUMMER = 2;
    public static final Integer AUTUMN = 3;
    public static final Integer WINTER = 4;
}

测试类

public class enumDemo01 {
    public static void main(String[] args) {
        switch (Season.SPRING) {
            case 1:
                System.out.println("Spring!");          // 具体的逻辑
                break;
            case 2:
                System.out.println("Summer!");           // 具体的逻辑
                break;
            case 3:
                System.out.println("Autumn!");          // 具体的逻辑
                break;
            case 4:
                System.out.println("Winter!");           // 具体的逻辑
                break;
        }

    }
}

2.2 枚举案例

Java 枚举类使用enum关键字来定义,各个常量使用逗号来分割。

public enum Season {
    SPRING,SUMMER,AUTUMN,WINTER
}

其中SPRINGSUMMERAUTUMNWINTER都是枚举项它们都是本类的实例,本类一共就只有四个实例对象。并且只能通过这四个关键字获取Season类的示例对象,不能使用new来创建枚举类的对象

public class EnumTest {
    public static void main(String[] args) {
        Season spring = Season.SPRING;
        Season summer = Season.SUMMER;
        Season autumn = Season.AUTUMN;
        Season winter = Season.WINTER;

        Season season = Season.SPRING;
        System.out.println(season == spring);//true
    }
}

2.3 枚举与switch

使用枚举,能让我们的代码可读性更强。

public class EnumTest02 {
    public static void main(String[] args) {
        Season season = Season.AUTUMN;

        switch (season){
            case SPRING:
                System.out.println("春天~");
                break;
            case SUMMER:
                System.out.println("夏天!");
                break;
            case AUTUMN:
                System.out.println("秋天@");
                break;
            case WINTER:
                System.out.println("冬天&");
                break;
            default:
                System.out.println("错误的季节");
        }
    }
}

3. 枚举的用法

3.1 枚举类的成员

枚举类和正常的类一样,可以有实例变量,实例方法,静态方法等等

定义枚举类:

package enumTest.enumTest03;

/**
 * @author 小宋学java
 * @version 1.0
 * @Data 2022/12/6 16:48
 * @Description TODO
 */
public enum enumTest03 {
    // 在枚举常量后面还有其他成员时,分号是必须的。枚举常量必须在枚举类中所有成员的上方声明
    RED,BLUE,GREEN,YELLOW;

    public String aaa="123";// 普通成员变量

    public static String bbb="456";// 静态成员变量

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public static void method(){
        System.out.println("enum hello~");
    }
}

Tips:当枚举项后面有其他成员(构造方法、成员变量、成员方法)时,最后一个枚举项必须加分号;

测试类:

package enumTest.enumTest03;

/**
 * @author 小宋学java
 * @version 1.0
 * @Data 2022/12/6 16:51
 * @Description TODO
 */
public class enumTest {
    public static void main(String[] args) {
        // 访问静态变量
        String bbb = enumDemo.bbb;

        // 访问静态成员方法
        enumDemo.method();

        // 通过枚举项获取实例
        enumDemo red = enumDemo.RED;

        // 通过枚举实例调用成员方法
        red.setName("红色");

        // 通过枚举实例调用成员方法
        System.out.println(red.getName());			// 红色
    }
}

3.2 枚举类的构造方法

3.2.1 枚举的无参构造方法

枚举类也可以有构造方法,构造方法默认都是private修饰,而且只能是private。因为枚举类的实例不能让外界来创建!

默认情况下,所有的枚举项的创建都是调用枚举类的无参构造方法

package enumTest.enumTest04;

/**
 * @author 小宋学java
 * @version 1.0
 * @Data 2022/12/6 16:59
 * @Description TODO
 */
public enum Direction {
    // 在枚举常量后面还有其他成员时,分号是必须的。枚举常量必须在枚举类中所有成员的上方声明
    FRONT,BEHIND,LEFT,RIGHT;

    // 枚举类的构造方法都是private修饰的,可写可不写
    Direction(){
        System.out.println("Direction创建了...");
    }

}

Tips:

  • 1:当枚举项后面有其他成员(构造方法、成员变量、成员方法)时,最后一个枚举项必须加分号;
  • 2:所有的枚举类的构造方法都是私有的(private关键字可加可不加)

测试类

package enumTest.enumTest04;

/**
 * @author 小宋学java
 * @version 1.0
 * @Data 2022/12/6 16:59
 * @Description TODO
 */
public class Test {
    public static void main(String[] args) {
        Direction direction=Direction.BEHIND;
    }
}
Direction创建了...
Direction创建了...
Direction创建了...
Direction创建了...

Tips:一旦创建了枚举实例,便会初始化里面的所有枚举项;创建枚举项就等同于调用本类的无参构造器,所以FRONT、BEHIND、LEFT、RIGHT四个枚举项等同于调用了四次无参构造器

3.2.2 枚举的有参构造方法

枚举项就是枚举类的实例,在创建定义枚举项时其实就是创建枚举类的实例,因此在定义枚举项就要传递实际的参数

package enumTest.enumTest05;

/**
 * @author 小宋学java
 * @version 1.0
 * @Data 2022/12/6 17:03
 * @Description TODO
 */
public enum Week {
    // 枚举项就是枚举类的实例,在创建定义枚举项时其实就是创建枚举的实例,因此在定义枚举项就要传递实际的参数
    MONDAY("星期一",1),
    TUESDAY("星期二"),
    WEDNESDAY,
    THURSDAY("星期四",3),
    FRIDAY("星期五",4),
    SATURDAY("星期六",5),
    SUNDAY("星期六",4);

    private String name;
    private Integer loveLevel;

    Week() {
    }

    
    Week(String name, Integer loveLevel) {
        this.name = name;
        this.loveLevel = loveLevel;
    }

    Week(String name) {
        this.name = name;
    }
}

测试类:

package enumTest.enumTest05;

/**
 * @author 小宋学java
 * @version 1.0
 * @Data 2022/12/6 17:07
 * @Description TODO
 */
public class Test {
    public static void main(String[] args) {
        Week friday = Week.FRIDAY;
        friday.show();
        System.out.println(friday);
        System.out.println("---------------");

        Week saturday = Week.SATURDAY;
        saturday.show();
        System.out.println(saturday);
        System.out.println("---------------");

        Week tuesday = Week.TUESDAY;
        tuesday.show();
        System.out.println(tuesday);
        System.out.println("---------------");

        Week wednesday = Week.WEDNESDAY;
        wednesday.show();
        System.out.println(wednesday);
        System.out.println("---------------");
    }
}

3.2.3 枚举中的抽象方法

枚举类中可以包含抽象方法,但是在定义枚举项时必须重写该枚举类中的所有抽象方法;

我们前面说过,每一个枚举项其实都是枚举类的实例对象,因此如果当前枚举类包含抽象方法时,在定义枚举项时就需要重写此枚举类的所有抽象方法,这跟我们以前使用的匿名内部类很相似;

首先定义一个抽象类(包含了抽象方法):

public abstract class AbstractSeason {
    
    public abstract void fund();
}

实例化这个抽象类的时候,我们必须抽象其所有的抽象方法:

// 可以把abstractSeason看做是一个枚举项,在定义枚举项时必须重写枚举类的所有抽象方法
        AbstractSeason abstractSeason = new AbstractSeason() {
            @Override
            public void fund() {
                System.out.println("重写了这个抽象类的所有抽象方法");
            }
	};

当枚举类中含有抽象方法的时候,定义枚举项时,必须重写该枚举类中所有的抽象方法,

package enumTest.enumTest06;

/**
 * @author 小宋学java
 * @version 1.0
 * @Data 2022/12/6 17:36
 * @Description TODO
 */
public enum Season {

    //SPRING; // 编译报错,定义枚举项时必须重写枚举类包含的所有抽象方法

    SPRING(){
        @Override
        public void fun() {
            System.out.println();
        }
    };

    public abstract void fun();
}

4. Enum 类

4.1 Enum类中的方法

Java中,所有的枚举类都默认继承与java.lang.Enum类,这说明Enum中的方法所有枚举类都拥有。另外Enum也继承与Object,因此所有的枚举类都拥有与Object类一样的方法;

Enum类中的方法如下:

Tips:枚举类除了不能拥有Object中的clone、finalize方法外,其他方法都能拥有;

Enum类新增(或重写Object)的方法:

  • int compareTo(E e):比较两个枚举常量谁大谁小,其实比较的就是枚举常量在枚举类中声明的顺序(ordinal值)

  • boolean equals(Object o):比较两个枚举常量是否相等;

  • Class getDeclaringClass():返回此枚举类的Class对象,这与Object中的getClass()类似;

  • int hashCode():返回枚举常量的hashCode

  • String name():返回枚举常量的名字;

  • int ordinal():返回枚举常量在枚举类中声明的序号,第一个枚举常量序号为0;

  • String toString():把枚举常量转换成字符串

  • static T valueOf(Class enumType, String name):把字符串转换成枚举常量。

4.2 枚举的两个抽象方法

每个枚举类都有两个静态方法,而且这两个方法不是父类中的方法。这又是枚举类特殊的地方;

  • static T[] values():返回本类所有枚举项;

4. Enum 类

4.1 Enum类中的方法

Java中,所有的枚举类都默认继承与java.lang.Enum类,这说明Enum中的方法所有枚举类都拥有。另外Enum也继承与Object,因此所有的枚举类都拥有与Object类一样的方法;

Enum类中的方法如下:

[外链图片转存中…(img-6VmM7J42-1670480758453)]

Tips:枚举类除了不能拥有Object中的clone、finalize方法外,其他方法都能拥有;

Enum类新增(或重写Object)的方法:

  • int compareTo(E e):比较两个枚举常量谁大谁小,其实比较的就是枚举常量在枚举类中声明的顺序(ordinal值)

  • boolean equals(Object o):比较两个枚举常量是否相等;

  • Class getDeclaringClass():返回此枚举类的Class对象,这与Object中的getClass()类似;

  • int hashCode():返回枚举常量的hashCode

  • String name():返回枚举常量的名字;

  • int ordinal():返回枚举常量在枚举类中声明的序号,第一个枚举常量序号为0;

  • String toString():把枚举常量转换成字符串

  • static T valueOf(Class enumType, String name):把字符串转换成枚举常量。

4.2 枚举的两个抽象方法

每个枚举类都有两个静态方法,而且这两个方法不是父类中的方法。这又是枚举类特殊的地方;

  • static T[] values():返回本类所有枚举项;
  • static T valueOf(String name):通过枚举项的名字返回枚举项
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值