韩顺平零基础30天学会Java【章9 枚举类和注解】

P425~P442

要求创建季节对象,设计并完成,com.enumeration.Enumeration01.java

public class Enumeration01 {
    public static void main(String[] args) {
        //因为对于季节而说,他的对象(具体值)是固定的,不会有更多
        Season spring = new Season("春天", "温暖");
        Season winter = new Season("冬天", "寒冷");
        Season summer = new Season("夏天", "炎热");
        Season autumn = new Season("秋天", "凉爽");
    }
}

class Season {
    private String name;
    private String desc;//描述

    public Season(String name, String desc) {
        this.name = name;
        this.desc = desc;
    }
}

枚举类实现方式

  1. 自定义类实现枚举
  2. 使用enum关键字实现枚举

自定义类实现枚举,com.enumeration.Enumeration02.java

  1. 不需要提供set方法,因为枚举对象值通常为只读
  2. 对枚举对象/属性使用final+static共同修饰,实现底层优化
  3. 枚举对象名通常使用全部大写,常量的命名规范
  4. 枚举对象根据需要,也可以有多个属性
public class Enumeration02 {
    public static void main(String[] args) {
        //因为对于季节而说,他的对象(具体值)是固定的,不会有更多
        System.out.println(Season02.AUTUMN);
    }
}

//自定义枚举
class Season02{
    private String name;
    private String desc;//描述
    //1、将构造器私有化,防止直接被new
    //2、去掉set方法,防止属性被修改
    //3、在内部创建固定的值
    public static final Season02 SPRING = new Season02("春天", "温暖");
    public static final Season02 WINTER = new Season02("冬天", "寒冷");
    public static final Season02 SUMMER = new Season02("夏天", "炎热");
    public static final Season02 AUTUMN = new Season02("秋天", "凉爽");
    private Season02(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 "Season02{" +
                "name='" + name + '\'' +
                ", desc='" + desc + '\'' +
                '}';
    }
}

自定义类实现枚举,特点:

  1. 构造器私有化
  2. 类内部创建一组对象
  3. 对外暴露对象,为对象添加public final static 修饰
  4. 可以提供get方法,但不提供set方法

enum关键字实现枚举,com.enumeration.Enumeration03.java

public class Enumeration03 {
    public static void main(String[] args) {
        System.out.println(Season03.AUTUMN);
    }
}

//使用enum替代class
enum Season03 {
    //public static final Season03 WINTER = new Season03("冬天", "寒冷");
    //使用SPRING("春天","温暖")
    //常量名(实参列表)
    //如果有多个常量,使用逗号间隔
    //要求常量对象写在最前面
    SPRING("春天", "温暖"),
    WINTER("冬天", "寒冷"),
    SUMMER("夏天", "炎热"),
    AUTUMN("秋天", "凉爽");
    private String name;
    private String desc;//描述
    private Season03(String name, String desc) {
        this.name = name;
        this.desc = desc;
    }
    public String getName() {
        return name;
    }
    public String getDesc() {
        return desc;
    }
}

enum注意事项

  1. 当我们使用enum关键字开发一个枚举类时,默认会继承Enum类,并且变成final类
  2. public static final Season SPRING = new Season(“春天”,“温暖”),简化成SPRING(“春天”,“温暖”)
  3. 如果使用无参构造器创建枚举对象,则实参列表和小括号都可以省略
  4. 当有多个枚举对象时,使用逗号间隔,最后一个分号结尾
  5. 枚举对象必须放在枚举类的首行

enum常用方法说明

使用关键字enum时,会隐式继承Enum类,这样我们就可以使用Enum类相关方法

public abstract class Enum<E extends Enum<E>> 
 implements Comparable<E>,SErializable{
}

常用方法

  • toString:返回当前对象名,子类可以重写该方法,用于返回对象的属性信息
  • name:返回当前对象名
  • ordinal:返回当前对象的位置号,默认从0开始
  • values:返回当前枚举类中所有的常量
  • valueOf:将字符串转换成枚举对象,要求字符串必须为已有常量名
  • compareTo:比较两个枚举常量,比较的是位置号

练习,com.enumeration.EnumerationExercise.java

  1. 声明Week枚举类,包含MONDAY,TUESDAY,WEDNEDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY
  2. 使用values返回所有的枚举数组,并遍历输出
public class EnumerationExercise {
    public static void main(String[] args) {
        for(Week day:Week.values()){
            System.out.println(day);
        }
    }
}

enum Week{
    MONDAY("星期一"),
    TUESDAY("星期二"),
    WEDNEDAY("星期三"),
    THURSDAY("星期四"),
    FRIDAY("星期五"),
    SATURDAY("星期六"),
    SUNDAY("星期天");
    private String name;

    Week(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return name;
    }
}

Enum实现接口

  1. 使用enum关键字后,就不能再继承其他类了,因为enum会隐式继承Enum,而java是单继承机制

  2. 枚举类和普通类一样,可以实现接口,如下

    enum 类名 implements 接口1,接口2{}

注解

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

使用Annotation时要在其前面增加@符号,并把该Annotation当成一个修饰符使用。

三个基本Annotation,com.anno.Annotation01.java

  1. @Override:限定某个方法,是重写父类方法,该注解只能用于方法
  2. @Deprecated:用于表示某个程序元素已过时
  3. @SuppressWarnings:抑制编译器警告
public class Annotation01 {
}
class Father {
    public void fly() {
    }
}
class Son extends Father {
    @Override
    //表示子类的fly是重写了父类的方法\
    //如果写了@Override,编译器会检查该方法是否真的重写了父类的方法
    // 如果的确重写了,则编译通过,如果没有构成重写,则编译错误
    public void fly() {
        super.fly();
    }
}

Override

  1. @Override表示指定重写父类的方法,如果父类没有该方法,则会报错
  2. 如果不写@Override注解,而父类有该方法,仍然构成重写
  3. @Override只能修饰方法,不能修饰其他类、包、属性等
  4. 查看@Override注解源码
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
1. @Target(ElementType.METHOD),说明只能修饰方法
2. @Target是修饰注解的注解,称为元注解
3. @interface,表示是一个注解类

Deprecated,com.anno.Deprecated_.java

public class Deprecated_ {
    public static void main(String[] args) {
        Dep a = new Dep();
        a.hi();
    }
}
@Deprecated
class Dep{
    public int n1=10;
    @Deprecated
    public void hi(){
        System.out.println("hi");
    }
}
  1. @Deprecated修饰某个元素,表示该元素已经过时
  2. 可以使用被修饰的元素,但是不推荐使用该元素
  3. 可以修饰方法、类、字段、包、参数等等
  4. 可以用作版本升级过渡和兼容
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, 
                METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}

SuppressWarnings,com.anno.SuppressWarnings_.java

import java.util.ArrayList;
import java.util.List;
public class SuppressWarnings_ {
    @SuppressWarnings({"all"})
    public static void main(String[] args) {
//        @SuppressWarnings 用来抑制警告信息
        List list = new ArrayList();
        list.add("jack");
        list.add("tom");
        list.add("mary");
        int i;
        System.out.println(list.get(1));
    }
}
  1. @SuppressWarnings用来抑制警告信息

@SuppressWarnings({“all”})

  1. unchecked:忽略没有检查的警告
  2. rawtypes:忽略没有指定泛型的警告
  3. unused:忽略没有使用某个变量的警告
  4. @SuppressWarnings:可以修饰的程序元素为,查看@Target
@Target({TYPE, FIELD, METHOD, PARAMETER, 
          CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    String[] value();//可以存放一个字符串数组,需要忽略的警告
}

元注解

元注解的种类

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

Retention

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

Retention三种值

  1. @Retention(RetentionPolicy.SOURCE):编译器使用后,直接丢弃这种策略的注释
  2. @Retention(RetentionPolicy.CLASS):编译器将把注释记录在class文件中,当运行java程序时,JVM不会保留注释。这是默认值
  3. @Retention(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类将被javadoc工具提取成文档,即在生成文档时,可以看到该注释。

说明:定义为Documented的注释必须设置Retention值为RUNTIME

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

Inherited

被他修饰的Annotation将具有继承性,如果某个类使用了被@Inherited修饰的Annotation,则其子类将自动具有该注释

作业

com.homwork.Homework0901.java

  1. 在Frock类声明私有的静态属性currentNum[int类型],初始值为100000,作为衣服出场的序列号起始值
  2. 声明公有的静态方法getNextNum,作为生成上衣唯一序列号的方法,每调用一次,将currentNum增加100,并作为返回值
  3. 在TestFrock类的main方法中,分两次调用getNextNum方法,获取序列号并打印输出
  4. 在Frock类中声明serialNumber(序列号)属性,并提供对应的get方法
  5. 在Frock类的构造器中,通过调用getNextNum方法为Frock对象获取唯一序列号,赋给serialNumber属性
  6. 在TestFrock类的main方法中,分别创建三个Frock对象,并打印三个对象的序列号,验证是否为按100递增/
//1. 在Frock类声明私有的静态属性currentNum[int类型],初始值为100000,作为衣服出场的序列号起始值
//2. 声明公有的静态方法getNextNum,作为生成上衣唯一序列号的方法,每调用一次,将currentNum增加100,
// 并作为返回值
//3. 在TestFrock类的main方法中,分两次调用getNextNum方法,获取序列号并打印输出
//4. 在Frock类中声明serialNumber(序列号)属性,并提供对应的get方法
//5. 在Frock类的构造器中,通过调用getNextNum方法为Frock对象获取唯一序列号,赋给serialNumber属性
//6. 在TestFrock类的main方法中,分别创建三个Frock对象,并打印三个对象的序列号,验证是否为按100递增

public class Homework0901 {
    public static void main(String[] args) {
        System.out.println(Frock.getNextNum());
        System.out.println(Frock.getNextNum());
        System.out.println(new Frock().getSerialNumber());
        System.out.println(new Frock().getSerialNumber());
        System.out.println(new Frock().getSerialNumber());
    }
}


class Frock {
    private static int currentNum = 100000;
    private int serialNumber;
    public Frock() {
        this.serialNumber = this.getNextNum();
    }
    public static int getNextNum() {
        currentNum += 100;
        return currentNum;
    }
    public int getSerialNumber() {
        return serialNumber;
    }
}

com.homwork.Homework0902.java

  1. 计算器接口具有work方法,功能是运算,有一个手机类Cellphone,定义方法testWork测试计算功能,调用计算接口的work方法
  2. 要求调用Cellphone对象的testWork方法,使用匿名内部类/
//1. 计算器接口具有work方法,功能是运算,有一个手机类CellPhone,
// 定义方法testWork测试计算功能,调用计算接口的work方法
//2. 要求调用CellPhone对象的testWork方法,使用匿名内部类/
public class Homework0902 {
    public static void main(String[] args) {

        new CellPhone().testWork(new Caculate() {
            @Override
            public void work(double n1,double n2) {
                System.out.println(n1+n2);
            }
        },1,2);
    }
}

interface Caculate{
    public void work(double n1,double n2);
}

class CellPhone{
    public void testWork(Caculate caculate,double n1,double n2){
        caculate.work(n1,n2);
    }
}

com.homwork.Homework0903.java

  1. 创建一个Color枚举类
  2. 有RED,BLUE,BLACK,YELLOW,GREEN这个五个枚举值/对象;
  3. Color有三个属性redValue, greenValue, blueValue,
  4. 创建构造方法,参数包括这三个属性,
  5. 每个枚举值都要给这三个属性赋值,三个属性对应的值分别是
  6. red: 255,0,0 blue:0,0,255 black:0,0.,0 yellow:255,255,0 green:0,255,0
  7. 定义接口,里面有方法show,要求Color实现该接口
  8. show方法中显示三属性的值
  9. 将枚举对象在switch语句中匹配使用
//1. 创建一个Color枚举类
//2. 有RED,BLUE,BLACK,YELLOW,GREEN这个五个枚举值/对象;
//3. Color有三个属性redValue, greenValue, blueValue,
//4. 创建构造方法,参数包括这三个属性,
//5. 每个枚举值都要给这三个属性赋值,三个属性对应的值分别是
//6. red: 255,0,0 blue:0,0,255 black:0,0.,0 yellow:255,255,0 green:0,255,0
//7. 定义接口,里面有方法show,要求Color实现该接口
//8. show方法中显示三属性的值
//9. 将枚举对象在switch语句中匹配使用
    
public class Homework0903 {
    public static void main(String[] args) {
        Color red = Color.RED;
        red.show();
        switch (red) {
            case YELLOW:
                System.out.println("匹配到黄色");
                break;
            case RED:
                System.out.println("匹配到红色");
                break;
        }
    }
}


interface ShowColor {
    public void show();
}

enum Color implements ShowColor {
    RED(255, 0, 0),
    BLUE(0, 0, 255),
    BLACK(0, 0, 0),
    YELLOW(255, 255, 0),
    GREEN(0, 255, 0);
    private int redValue;
    private int greenValue;
    private int blueValue;

    Color(int redValue, int greenValue, int blueValue) {
        this.redValue = redValue;
        this.greenValue = greenValue;
        this.blueValue = blueValue;
    }

    @Override
    public void show() {
        System.out.println("属性值为" + redValue + "," + greenValue + "," + blueValue);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_65656674/article/details/126416814