6. 枚举

枚举

列举,罗列。代表一系列的类型,这些类型有一个非常的明显的特征,就是他们的对象是有限的几个。枚举是 JDK 1.5 之后才有的。枚举类型也是类,原来用 class 声明类,现在用 enum 来声明枚举。

说明

  1. 枚举类型的构造器一定是私有的

  2. 枚举类型的常量对象列表必须在枚举类的首行

  3. 所有枚举类型有一个直接父类 java.lang.Enum 类型,所以不能在继承其他类。 java.lang.Enum 中已经复写了 toString 方法,返回的是常量的名字。

  4. switch… case 增加了对枚举的支持

package com.itguigu.com;

public class TestEnumType {
    public static void main(String[] args) {
        Week monday = Week.Monday;
        System.out.println(monday); // 枚举类默认继承自 java.lang.Enum,里面已经重写了 toString, 返回常量名称

        switch (monday) {
        case Monday:
            System.out.println("周一");
            break;
        default:
            System.out.println("未匹配到星期");
            break;
        }
    }
}


/**
 * 使用 enum 声明枚举类,默认继承自 java.lang.Enum 
 * @author rex
 *
 */
enum Week{
    Monday("星期一", "最难的一天"),  // 使用的是有参的构造。且常量对象列表必须在枚举类的首行
    Tuesday,                      // 使用的无参的构造
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday;

    private String name;
    private String desc;

    /**
     * 无参私有构造,默认就有
     */
    private Week() {

    }

    /**
     * 有参数私有构造
     * @param name
     * @param desc
     */
    private Week(String name, String desc) {
        this.name = name;
        this.desc = desc;
    }

    public String getName() {
        return name;
    }

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

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}
Monday
周一

java.lang.Enum中的方法

java.lang.Enum是所有 Java 语言枚举类型的公共基本类。即所有的枚举类型都继承它,不能在继承别的类型。

  1. name(): 返回此枚举常量的名称
  2. ordinal(): 返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为0)
  3. int compareTo(x):默认按照枚举对象的顺序排序
  4. API 中没有,编译器自动生成的方法:values(),valueOf(常量名)
package com.itguigu.com;

public class TestEnumType {
    public static void main(String[] args) {
        Week monday = Week.Monday;
        System.out.println(monday);                // Monday
        System.out.println(monday.name());         // Monday
        System.out.println(monday.ordinal());      // 0

        Week[] values = Week.values();
        for (int i = 0; i < values.length; i++) {
            System.out.println(values[i]);         // Monday Tuesday Wednesday Thursday Friday Saturday Sunday
        }

        Week valueOf = Week.valueOf("Monday");
        System.out.println(valueOf);               // Monday
    }
}


/**
 * 使用 enum 声明枚举类,默认继承自 java.lang.Enum 
 * @author rex
 *
 */
enum Week{
    Monday("星期一", "最难的一天"),  // 使用的是有参的构造。且常量对象列表必须在枚举类的首行
    Tuesday,                      // 使用的无参的构造
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday;

    private String name;
    private String desc;

    /**
     * 无参私有构造,默认就有
     */
    private Week() {

    }

    /**
     * 有参数私有构造
     * @param name
     * @param desc
     */
    private Week(String name, String desc) {
        this.name = name;
        this.desc = desc;
    }

    public String getName() {
        return name;
    }

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

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}

注解

注解由三部分组成:

  1. 声明注解,既定义注解(绝大部分都是别人定义好的)
  2. 使用注解
  3. 读取注解的信息。我们把读取注解信息的代码称之为 ”注解信息处理流程“。如果没有 “读取注解的信息” 的过程,前两步没有意义。读取注解的代码基本上也是别人写好的。读取注解的信息需要用到 “反射”。

1. 系统预定义的三个基本的注解

@Override:由 JDK 的核心库定义,它由编译器读取,例如 javac.exe。作用是表示方法是一个 “重写” 的方法,让编译器对这个方法的签名进行格式检查,检查是否符合 “重写” 的要求。被 static,final,private 修饰的方式是不能被重写的。

方法重写应该满足的要求:

  1. 方法名和形参列表必须相同

  2. 返回值类型:

    如果是基本数据类型和 void:必须相同

    引用数据类型:返回值应该是小于或者等于的关系(小于【子类】或者等于父类的返回值)

  3. 权限修饰符:大于等于父类的权限修饰符。

  4. 不是被 static,final,private 修饰的方法

@SuppressWarnings: 由 JDK 的核心库定义,它由编译器读取,例如 javac.exe。作用是抑制警告。

@Deprecated: 由 JDK 的核心库定义,它由编译器读取,例如 javac.exe。作用是标识,类,方法,属性已经过时,不建议再使用。

2. 文档注释

@param: 方法必须有行参,有几个行参就写几个。格式为 @param 形参名 行参数据类型 解析

@return:方法的返回值类型必须不是void,且一个方法就只能有一个@return。格式为 @return 返回值类型 解释

@throws:必须方法有 throws 异常才写,且有几个就写几个。格式为 @throws 类型 解释

package com.itguigu.com;

/**
 * 
 * @author rex
 * @version JDK1.8
 * @since JDK 1.5 
 */
public class TestDoc {
    /**
     * 主方法
     * @param args String[]
     */
    public static void main(String[] args) {

    }

    /**
     * 求两个整数的最大值
     * @param a int 
     * @param b int 
     * @return int 返回 a,b 中的最大值
     */
    public static int getMax(int a, int b) {
        return a>b?a:b;
    }

    /**
     * 求两个整数的商
     * @param a int 被除数
     * @param b int 除数
     * @return int 商
     * @throws RuntimeException 当除数为 0 时会抛出异常
     */
    public static int divide(int a, int b)throws RuntimeException {
        if (b==0) {
            throw new RuntimeException("除数不能为0");
        }else {
            return a/b;
        }
    }    
}

将注释导出为文档:

3. 单元测试相关

@Test: 加在方法上进行单元测试。被测试的方法的参数必须是 public,且返回值是 void,且无参数的。而且要求方法所在类也是 public 的。

@Before:在每一个 @Test 标记的方法之前运行

@After:在每一个 @Test 标记的方法之后运行

@BeforeClass:在当前类初始化时执行,方法必须是 static 修饰的。只执行一次。

@AfterClass:在所有方法运行之后运行,方法必须是 static 修饰的。只执行一次

目前 ide 都有 Junit 的 jar 包,我们直接添加就行。eclipse 步骤如下:

项目右键 -> Build Path -> Add library -> JUnit -> 选择版本 -> finish

package com.itguigu.com;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class TestJunit {
    @BeforeClass
    public static void init() {
        System.out.println("最先执行");
    }

    @Before
    public void test11() {
        System.out.println("每个 @Test 执行之前都会打印");
    }

    @After
    public void test11111() {
        System.out.println("每个 @Test 执行之后都会打印");
    }

    @AfterClass
    public static void test111() {
        System.out.println("最后执行");
    }

    @Test
    public void test1() {
        System.out.println("111");
    }

    @Test
    public void test1111() {
        System.out.println("222");
    }
}

自定义注解和元注解

元注解

元注解:元注解就是注解上面的注解

  1. @Target: 可以指定定义的注解用在什么位置上。位置由 ElementType 枚举的常量对象来指定。
  2. @Retention: 标记注解可以滞留到某个阶段,也就是注解的声明周期。由,RetentionPolicy 常量对象来指定。具体的值有 SOURCE(源代码阶段,默认),CLASS(字节码阶段),RUNTIME(运行时)

  3. @Documented: 标记注解是否可以被 javadoc.exe 读取到 API 中 (不常用)

  4. @Inherited: 标记注解是否能被子类继承

package com.itguigu.com;

import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

public class TestDefineAnnotation {
    public static void main(String[] args) {
        // 反射
        Class clazz = MyClass.class;
        MyAnnotation myAnnotation = (MyAnnotation) clazz.getAnnotation(MyAnnotation.class);
        System.out.println(myAnnotation);
    }
}

@MyAnnotation
class MyClass{
    @MyAnnotation
    public String testField;

    @MyAnnotation
    public void test() {};
}

/**
 * 自定义注解三个步骤:
 * 1. 声明注解
 * 2. 使用
 * 3. 读取
 * @author rex
 *
 */
@Target(value = { ElementType.METHOD, ElementType.FIELD, ElementType.TYPE}) // 表明 MyAnnotation 注解可以用在方法,属性和类上
@Retention(RetentionPolicy.RUNTIME)  // 将注解声明周期控制到运行时,这样在反射中才能使用
@interface MyAnnotation{

}

配置注解参数

配置参数的赋值

  1. 如果注解声明配置参数,那么在使用这个注解的时候就需要给配置参数赋值。格式为 ”配置参数名=参数值“。
  2. 如果配置参数的个数只有一个,并且名称是 value,那么可以省略 “配置参数名=”。
  3. 如果配置参数有默认值,那么可以不赋值。
  4. 配置参数的类型可以为 八种基本数据类型,String,Class,enum,Annotation,及以上所有类型的数组。
package com.itguigu.com;

public class TestAnnotionParam {

}

// 使用注解参数
@A
class B{

}

@interface A{
    // String info();

    // String value();

    String info() default "default value";
}

 上一篇
7. 异常 7. 异常
异常java.lang.Throwable 是 Java 语言中所有错误或异常的超类。 1. ErrorError 是 Throwable的子类,用于指示合理的应用程序不应该试图捕获的严重问题。例如 VirtualMachineError
2019-10-20
下一篇 
5. 内部类 5. 内部类
接口变化JDK 1.8 之后,接口的语法有了新的变化。增加了两类成员。 静态方法 public static。static 不可以省略,通过 “接口名.方法名” 来进行调用。 默认方法 public default。default 不可以
2019-10-14
  目录