十一、枚举 Enumeration(完结)

十一、枚举 Enumeration

11.1 枚举的引入

需求:用类表示季节

传统方法:声明 Season 类,有 name,temperature 两个属性,构造器,get,set 方法,创建四个对象表示四个季节

问题分析:

  • 季节只能有春夏秋冬固定的值,传统方法体现不出,需要有方法,使得季节只能有春夏秋冬四种
  • 并且里面的属性也不能修改

引入枚举类(Enumeration,简写Enum):

  • 枚举是一组常量的集合。
  • 可以这里理解:枚举属于一种特殊的类,里面只包含一组有限的特定的对象。

11.2 枚举类的两种实现方式

自定义枚举类

  1. 私有化构造器,防止外部再创建对象
  2. 不需要提供 setXxx 方法,因为枚举对象值通常为只读.

  3. 对外暴露对象 public final static 共同修饰,实现底层优化.

  4. 枚举对象名通常使用全部大写,常量的命名规范.

  5. 枚举对象根据需要,也可以有多个属性

package com.hspedu.enum_;

/**
 * @author: Carl Zhang
 * @create: 2021-11-23 14:20
 */
public class Enumeration01 {
    public static void main(String[] args) {
        //创建四个对象表示四个季节
        //Season season1 = new Season("春天");
        //Season season2 = new Season("夏天");
        //Season season3 = new Season("秋天");
        //Season season4 = new Season("冬天");
        //Season season5 = new Season("今天");

        //问题分析:
        //季节只能有春夏秋冬固定的值,传统方法体现不出
        //需要有方法,使得季节只能有春夏秋冬四种
        //并且里面的属性也不能修改 -- 引入枚举类

        System.out.println(Season.SPRING.toString());
        System.out.println(Season.SUMMER.toString());
        System.out.println(Season.AUTUMN.toString());
        System.out.println(Season.WINTER.toString());
    }
}

//要求创建季节 ( Season ) 对象,请设计并完成
class Season {
    private String name;
    //5. 枚举对象根据需要,也可以有多个属性
    private String temperature;

    public String getTemperature() {
        return temperature;
    }

    //3. 对枚举对象 public + final + static 共同修饰,实现底层优化.

    //4. 枚举对象名通常使用全部大写,常量的命名规范.

    public static final Season SPRING = new Season("春天", "温暖");
    public static final Season SUMMER = new Season("夏天", "炎热");
    public static final Season AUTUMN = new Season("秋天", "萧瑟");
    public static final Season WINTER = new Season("冬天", "寒冷");

    //1. 私有化构造器,防止外部再创建对象
    private Season(String name, String temperature) {
        this.name = name;
        this.temperature = temperature;
    }

    public String getName() {
        return name;
    }

    //2. 不需要提供 setXxx 方法,因为枚举对象值通常为只读.

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

    @Override
    public String toString() {
        return "季节:" + name + ", 温度:" + temperature;
    }
}

使用 enum 关键字

  1. enum 代替 class
  2. public static final Season2 SPRING = new Season2("春天", "温暖")SPRING("春天", "温暖") ,(即常量(参数列表)) 代替
  3. 常量对象定义语句要写在第一行
  4. 多个常量对象用 , 隔开,结尾用 ;
  5. 常量对象调用的是构造器根据参数列表决定,调用无参构造可以参数列表和小括号都不写
public class Enumeration02 {
    public static void main(String[] args) {
        System.out.println(Season2.SPRING);
        System.out.println(Season2.SUMMER);
        System.out.println(Season2.AUTUMN);
        System.out.println(Season2.WINTER);
        System.out.println(Season2.TEST);
    }
}

//要求创建季节 ( Season ) 对象,请设计并完成
//1. enum 代替class
enum Season2 {
    //public static final Season2 SPRING = new Season2("春天", "温暖");
    //public static final Season2 SUMMER = new Season2("夏天", "炎热");
    //public static final Season2 AUTUMN = new Season2("秋天", "萧瑟");
    //public static final Season2 WINTER = new Season2("冬天", "寒冷");

    //用enum关键字表示枚举类:
    //2. public static final Season2 SPRING = new Season2("春天", "温暖"); 用SPRING("春天", "温暖");代替
    //3. 常量对象定义语句要写在第一行
    //4. 多个常量对象用 , 隔开
    //5. 常量对象调用的是构造器根据参数列表决定,调用无参构造可以参数列表和小括号都不写
    SPRING("春天", "温暖"),
    SUMMER("夏天", "炎热"),
    AUTUMN("秋天", "萧瑟"),
    WINTER("冬天", "寒冷"),
    TEST;

    private String name;
    private String temperature;

    private Season2(String name, String temperature) {
        System.out.println("有参构造被调用");
        this.name = name;
        this.temperature = temperature;
    }

    private Season2() {
        System.out.println("无参构造被调用");
    }

    public String getName() {
        return name;
    }

    public String getTemperature() {
        return temperature;
    }

    @Override
    public String toString() {
        return "季节:" + name + ", 温度:" + temperature;
    }
}

11.3 enum 关键字的注意事项和细节

  • 当我们使用 enum 关键字开发一个枚举类时,默认会继承 Enum 类, 而且是一个 final

十一、枚举 Enumeration(完结)
  • 传统的 public static final Season2 SPRING = new Season2("春天", "温暖"); 简化成 SPRING("春天", "温暖") , 这里必须知道,它调用的是哪个构造器.

  • 如果使用无参构造器创建枚举对象,则实参列表和小括号都可以省略

  • 当有多个枚举对象时,使用 , 间隔,最后有一个分号结尾
  • 枚举对象必须放在枚举类的行首

11.4 Enum 类常用方法

前面已经知道:使用 enum 关键字,会隐式继承 Enum 类,所以能直接调用 Enum 类的方法,看下图源码定义:

十一、枚举 Enumeration(完结)
常用方法:
  1. toString() : Enum 类已经重写过了,返回的是当前对象 名,子类可以重写该方法,用于返回对象的属性信息
  2. name() :返回当前对象名(常量名),子类中不能重写
  3. ordinal() :返回当前对象的位置号,默认从 0 开始
  4. values() :返回当前枚举类中所有的常量的对应对象数组
  5. valueOf() :将字符串转换成枚举对象,要求字符串必须为已有的常量名,否则报异常!
  6. compareTo() :比较两个枚举常量,比较的就是编号!
public class EnumMethod {
    public static void main(String[] args) {
        Season2 summer = Season2.SUMMER;

        //1.toString:Enum 类已经重写过了,返回的是当前对象 名,子类可以重写该方法,用于返回对象的属性信息
        System.out.println("summer.toString() = " + summer.toString()); //Season未重写时: SUMMER

        //2.name:返回当前对象名(常量名),子类中不能重写
        System.out.println("summer.name() = " + summer.name()); //SUMMER

        //3.ordinal:返回当前对象的位置号,默认从 0 开始
        System.out.println("summer.ordinal() = " + summer.ordinal()); //1

        //4.values:返回当前枚举类中所有的常量的对应对象数组
        Season2[] season2s = Season2.values();
        for (Season2 season2 : season2s) { //增强型 for 循环
            System.out.println(season2);
        }

        //5.valueOf:将字符串转换成枚举对象,要求字符串必须 为已有的常量名,否则报异常!
        Season2 winter = Season2.valueOf("WINTER");
        System.out.println("winter = " + winter);

        //6.compareTo:比较两个枚举常量,比较的就是编号!
        // 返回的是 winter.compare - Season.WINTER.compare
        System.out.println("winter.compareTo(Season.WINTER) = " + winter.compareTo(Season2.WINTER)); //0
    }
}

11.5 enum 实现接口

  • 使用 enum 关键字后,就不能再继承其它类了,因为 enum 会隐式继承 Enum,而 Java 是单继承机制。
  • 枚举类和普通类一样,可以实现接口,语法: enum 类名 implements 接口 1,接口 2 {}
public class EnumDetail {
    public static void main(String[] args) {
        Music.CLASSIC_MUSIC.playing();
    }
}

interface IPlaying {
    public void playing();
}

//1) 使用 enum 关键字后,就不能再继承其它类了,因为 enum 会隐式继承 Enum,而 Java 是单继承机制。
//2) 枚举类和普通类一样,可以实现接口,如下形式。 enum 类名 implements 接口 1,接口 2{}
enum Music implements IPlaying {
    CLASSIC_MUSIC;

    @Override
    public void playing() {
        System.out.println("播放经典歌曲");
    }
}

11.6 注解的介绍

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

11.7 基本 Annotation 介绍

介绍:使用 Annotation 时要在其前面增加 @ 符号, 并把该 Annotation 当成一个修饰符使用。用于修饰它支持的程序元素

三个基本的 Annotation:

  • @Override : 表示某个方法是重写父类方法, 该注解只能用于方法
  • @Deprecated : 用于表示某个程序元素(类, 方法等)已过时
  • @SuppressWarnings : 抑制编译器警告

11.8 Annotation 应用案例

11.8.1 @Override 注解案例

class Father {
    void speak() {
        System.out.println("我是爸爸");
    }
}

class Son extends Father {
    //3. 看看 @Override 定义
    /**
     * @Target(ElementType.METHOD)  //表示只能作用于方法,@Target 是修饰注解的注解,即元注解
     * @Retention(RetentionPolicy.SOURCE)
     * public @interface Override { //@interface 表示该类是一个注解类
     * }
     */
    @Override
    void speak() {
        System.out.println("我是儿子");
        ;
    }

    //1. 不加 @Override ,只要语法构成重写关系,也会认定为重写
    //void speak() {
    //    System.out.println("我是儿子");
    //}

    //2. 加了 @Override , 编译器会对方法做重写语法的检查,如果方法语法不是重写,编译不通过
    //@Override
    //void speak(String name) {
    //    System.out.println("我是" + name);
    //}

}

注意事项:

  1. @Override 表示该方法重写父类方法(从编译层面验证),如果该方法语法不构成重写,则编译不通过
  2. 如果不写 @Override 注解,只要语法构成重写关系,也会认定为重写
  3. @Override 只能修饰方法,不能修饰其它类,包,属性等等
  4. 查看 @Override 注解源码为 @Target(ElementType.METHOD) ,说明只能修饰方法
  5. @Target 是修饰注解的注解,称为元注解,记住这个概念。

11.8.2 @Deprecated 注解案例

public class Deprecated_ {
    public static void main(String[] args) {
        A a = new A();
        a.name = "张三";
        a.speak();
    }
}

//2. 查看 @Deprecated 注解类的源码
/**
 * @Documented
 * @Retention(RetentionPolicy.RUNTIME)
 * @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE}) //3可以修饰方法,类,字段, 包, 参数 等等
 * }
 */
//4. @Deprecated 可以做版本升级过渡使用

//1. @Deprecated 修饰某个元素, 表示该元素已经过时, 即不在推荐使用,但是仍然可以使用
@Deprecated
class A {
    @Deprecated
    String name;

    @Deprecated
    public void speak() {
        System.out.println("我叫" + name);
    }
}

注意事项:

  1. @Deprecated 修饰某个元素, 表示该元素已经过时, 即不在推荐使用,但是仍然可以使用
  2. 查看 @Deprecated 注解类的源码 @Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE}),表示可以修饰方法,类,字段, 包, 参数 等等
  3. @Deprecated 可以做版本升级过渡使用

11.8.3 @SuppressWarnings 注解的案例

@SuppressWarnings : 抑制编译器警告

@SuppressWarnings({"rawtypes", "unchecked", "unused"}) //作用于这个类
public class SuppressWarnings_ {
    //3. 关于 SuppressWarnings 作用范围是和你放置的位置相关
    //比如 @SuppressWarnings 放置在 main 方法,那么抑制警告的范围就是 main
    //通常我们可以放置具体的语句, 方法, 类.

    //@SuppressWarnings({"rawtypes", "unchecked", "unused"})
    public static void main(String[] args) {

        //4. 看看 @SuppressWarnings 源码
        /**
         * @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) // 4.1作用位置
         * @Retention(RetentionPolicy.SOURCE)
         * public @interface SuppressWarnings {
         *      String[] value (); //4.2表示可以传入String类型数组的参数{"rawtypes", "unchecked", "unused"}
         *}
         */
        //1. 当我们不希望看到这些警告的时候,可以使用 SuppressWarnings 注解来抑制警告信息
        //2. 在{""} 中,可以写入你希望抑制(不显示)警告信息
        //@SuppressWarnings("rawtypes") //作用于该语句
        List list = new ArrayList();
        list.add("jack");
        list.add("tom");
        list.add("mary");
        int i;
        System.out.println(list.get(1));
    }

    public void method01() {
        List list = new ArrayList();
        list.add("jack");
        list.add("tom");
        list.add("mary");
        int i;
        System.out.println(list.get(1));
    }
}

注意事项:

  • @SuppressWarnings 放在哪个元素位置,就对该元素的警告起作用
  • @SuppressWarnings 可以修饰的程序元素为 @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
  • 可传入的参数,不用背,直接点击左侧的黄色提示,就可以选择(注意可以指定生成的位置)
    | 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 | 抑制与未用的程式码及停用的程式码相关的警告 |

十一、枚举 Enumeration(完结)

11.9 JDK 的元 Annotation(了解即可)

11.9.1 元注解基本介绍

元注解:修饰注解的注解,现在使用不多,主要是为了看懂源码

11.9.2 元注解的种类

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

11.9.3 @Retention 注解

介绍:

  • 只能用于修饰一个 Annotation , 用于指定该 Annotation 可以保留多长时间
  • @Rentention 包含一个 RetentionPolicy(策略)类型的成员变量 value , 使用 @Rentention 时必须为该 value 成员变量赋值
  • @Retention 的三种值(分别对应 java 程序的三个阶段):
  • RetentionPolicy.SOURCE:编译器使用后,直接丢弃这种策略的注解
  • RetentionPolicy.CLASS :编译器将把注解记录在 class 文件中,当运行 Java 程序时 JVM 不会保留注解,这是默认值
  • RetentionPolicy.RUNTIME :编译器将把注解记录在 class 文件中. 当运行 Java 程序时, JVM 会保留注解,程序可以通过反射获取该注解

案例:

十一、枚举 Enumeration(完结)

11.9.4 @Target 注解

介绍:用于修饰 Annotation ,用于指定被修饰的 Annotation 能用于修饰哪些程序元素 @Target 也包含一个 ElementType 数组类型的名为 value 的成员变量。
案例:见之前 Annotation 案例

十一、枚举 Enumeration(完结)

11.9.5 @Documented 注解

介绍:

  • @Documented :用于指定被该元 Annotation 修饰的 Annotation 类将被 javadoc 工具提取成文档,即在生成文档时,可以看到该注解。
  • 注意:定义为 @Documented 的注解必须设置 @Retention 值为 RUNTIME

案例:

十一、枚举 Enumeration(完结)

11.9.6 @Inherited 注解

介绍:被它修饰的 Annotation 将具有继承性.如果某个类使用了被 @Inherited 修饰的 Annotation,则其子类将自动具有该注解(实际应用中,使用较少,了解即可)

11.10 自定义注解

11.10.1 自定义注解的格式

  • **格式 :@interface *
修饰符 @interface 注解名{ //本质上是一个接口
   // 常量
   // 抽象方法 【注解中的抽象方法我们称为属性】,返回值类型必须是特定的,必须是无参的
   // 特定的返回值类型 : String,Class类型,注解类型,枚举类型 , 基本数据类型,以及这些类型的一维数组。
   类型 属性名(); // 使用的过程可以赋值
   类型 属性名() default 值; // 也可以在定义的过程中给出默认值
}
  • 案例:定义一个书(Book )的注解,包含属性书名(name ),价格(price )(默认 100 ),作者(author ) , 作者要求可以有多名作者
public @interface Book {
    String name();

    double price() default 100;

    String[] author();
}

11.10.2 注意事项和使用细节

  • 自定义注解主要是可以给某些成分注入信息,注入一些数据
  • 可以使用在类上,成员变量上,构造方法上,方法上 …

  • 有默认值的属性,可以不用进行赋值,也可以重新修改值

  • 如果属性是数组,赋值时若有多个数据需要使用大括号括起来,逗号分隔数据 , 如果数组中只有一个元素, 那么大括号可以省略
  • 如果注解中只有一个属性要赋值,而且名字是 value 。可以将 value 给省略,可以直接给值

11.10.3 自定义注解的使用格式

  • *格式 :
@注解名(属性=值 , 属性=值)

@Book(name="西游记" , author="吴承恩")
  • 案例:创建一个 BookStore 的类,在类中定义成员变量,构造方法,成员方法 , 使用 Book 注解给这些成分注入信息
package com.itheima.annotation_demo;
/*
    给成员注入四大名著信息 :
        西游记     --- 吴承恩
        水浒传     --- 施耐庵
        三国演义   --- 罗贯中
        红楼梦     --- 曹雪芹 , 高鹗
 */

@Book(name = "西游记", author = {"吴承恩"})
public class BookStore {

    @Book(name = "水浒传", price = 200, author = {"施耐庵"})
    private String name;

    @Book(name = "三国演义", author = {"罗贯中"})
    public BookStore(String name) {
        this.name = name;
    }

    @Book(name = "红楼梦", author = {"罗贯中", "高鹗"})
    public void buy() {
    }
}
public class Demo01 {
    @A("Hello")
    public void test1() {
    }

    @B("World")
    public void test2() {

    }

    @B(value = "Hello", price = 10)
    public void test3() {

    }
}

@interface A {
    String value();
}

@interface B {
    String value();

    int price() default 100;
}

11.10.4 解析注解,见 — 二十、反射

11.11 练习

11.11.1 唐僧过河问题

  1. 有一个交通工具接口类 Vehicles ,有 work 接口
  2. 有 Horse 类和 Boat 类分别实现 Vehicles
  3. 创建交通工具工厂类,有两个方法分别获得交通工具Horse和Boat
  4. 有 Person 类,有 name 和 Vehicles 属性,在构造器中为两个属性赋值
  5. 实例化 Person 对象”唐僧”,要求一般情况下用 Horse 作为交通工具,遇到大河时用 Boat 作为交通工具
  6. 扩展 — 遇到火焰山时坐飞机 Plane
//1.有一个交通工具接口类Vehicles,work方法
public interface Vehicles {
    void work();
}

//2.有Horse类和Boat类分别实现Vehicles
public class Horse implements Vehicles {

    @Override
    public void work() {
        System.out.println("在路上骑马");
    }
}

public class Boat implements Vehicles {

    @Override
    public void work() {
        System.out.println("在水上乘舟");
    }
}

package com.hspedu.annotation_;

//3.创建交通工具工厂类,有两个方法分别获得交通工具Horse和Boat
public class Factory {

    //问题:走路的时候,马可以一直是同一条不用换,原来的方法每次都要创建对象
    //优化:使用饿汉式
    private static Horse horse = new Horse();

    private Factory() {}

    public static Horse getHorse() {
        return horse;
    }

    ////获得Horse对象
    //public static Horse getHorseInstance() {
    //    return new Horse();
    //}

    //获得Boat对象
    public static Boat getBoat() {
        return new Boat();
    }

    //使用匿名内部类创建飞机 -- 会出现多次使用飞机类情况,此处不适用匿名内部类
    //public static Vehicles getPlane() {
    //    return new Vehicles() {
    //        @Override
    //        public void work() {
    //            System.out.println("飞机在天上飞");
    //        }
    //    };
    //}

    public static Plane getPlane() {
        return new Plane();
    }
}

package com.hspedu.annotation_;

//4.有Person类,有name和Vehicles属性,在构造器中为两个属性赋值
public class Person {
    private String name;
    private Vehicles vehicle;

    public Person(String name, Vehicles vehicle) {
        this.name = name;
        this.vehicle = vehicle;
    }

    public String getName() {
        return name;
    }

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

    public Vehicles getVehicle() {
        return vehicle;
    }

    public void setVehicle(Vehicles vehicle) {
        this.vehicle = vehicle;
    }

    //要求一般情况下用Horse作为交通工具,遇到大河时用Boat作为交通工具
    //用 OOP 思想,创建方法解决问题
    public void takeBoat() {
        //因为创建对象时,分配了一个交通工具,所以这里要判断,该交通工具是否已经分配了
        if (!(vehicle instanceof Boat))
            vehicle = Factory.getBoat();

        vehicle.work();
    }

    public void Ridding() {
        //因为创建对象时,分配了一个交通工具,所以这里要判断,该交通工具是否已经分配了
        if (!(vehicle instanceof  Horse))
            vehicle = Factory.getHorse();

        vehicle.work();
    }

    //扩展:遇到火焰山时候 坐飞机
    //使用匿名内部类的方式 -- 实际开发中,飞机类可能有多次使用情况,此处不适用匿名内部类
    //创建新的飞机类,工厂创建产生飞机的方法,再通过工厂产生飞机
    public void fly() {
        //问题,如果一开始就是分配的飞机
        // 解决:因为飞机使用的也是同一架,用 == 判断
        //vehicle = Factory.getPlane();
        //if (vehicle != Factory.getPlane())
        //    vehicle = Factory.getPlane();

        if (!(vehicle instanceof Plane))
            vehicle = Factory.getPlane();

        vehicle.work();
    }
}

public class Homework06 {
    public static void main(String[] args) {
        //要点:
        // 1. 用工厂类实现生产对象,将马设计成单例
        // 2. 用方法实现坐船,坐车,坐飞机的功能
        // 3. 用instanceof 判断对象是否已存在,从而避免对象重复创建

        //|5.实例化Person对象"唐僧",要求一般情况下用Horse作为交通工具,遇到大河时用Boat作为交通工具
        Person person = new Person("唐僧", Factory.getPlane());

        //平时骑马
        person.Ridding();
        //遇到水坐船
        person.takeBoat();
        //遇到火焰山坐飞机
        person.fly();
        person.fly();
        person.fly();
        person.fly();
    }
}

//扩展 -- 遇到火焰山坐飞机,创建新的飞机实体类
public class Plane implements Vehicles {

    @Override
    public void work() {
        System.out.println("飞机在天上飞");
    }
}

Original: https://www.cnblogs.com/Carl-Zhang/p/15763037.html
Author: Carl-Zhang
Title: 十一、枚举 Enumeration(完结)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/685901/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Golang context

    Context Go 语言中提供了 context 包,通过显示传递 context, 实现请求级别的元数据、取消信号、终止信号的传递。context 包提供了从现有的上下文值(c…

    技术杂谈 2023年7月11日
    073
  • phpcms全文检索功能实现(集成sphinx)

    sphinx配置 sphinx是俄罗斯人开发的一个搜索引擎,基于c++编写,具有强大的检索能力,本身支持中文单个字符的检索,中文分词需要额外的插件Coreseek,但该插件已很久未…

    技术杂谈 2023年7月11日
    0107
  • 报错:OSError: libnccl.so.2: cannot open shared object file: No such file or directory

    因为没有安装nccl,本机为centos7 https://developer.nvidia.com/nccl/nccl-legacy-downloads 需要登录一下 得到ncc…

    技术杂谈 2023年6月1日
    0102
  • 聊聊运营活动的设计与实现逻辑

    产品留不住,唯有套路得用户; 一、业务背景 在多数的产品功能体系中,都会设计活动板块,活动作为运营的手段,根本目的是为了更好的连接产品和用户,所以很考验运营方案的策划,在活动的生命…

    技术杂谈 2023年7月23日
    095
  • Linux查看日志文件写入速度的4种方法

    原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。 简介 有时,我们需要查看某个文件的增长速度,如日志文件,以此来感受系统的负载情况,因为一般情况下,日…

    技术杂谈 2023年7月24日
    083
  • ensp学习-1 ensp无法运行启动问题解决

    1、40错误管理员:bcdedit /set hypervisorlaunchtype off2、41错误2.1,先备份ensp vboxserver目录,打开vbox中右上角全局…

    技术杂谈 2023年6月1日
    0104
  • Unable to find IPv4-only network bridge for LXD.

    https://github.com/conjure-up/conjure-up/issues/1440It seems like the the installation is …

    技术杂谈 2023年5月31日
    079
  • HashMap原理及源码分析

    HashMap 原理及源码分析 1. 存储结构 HashMap 内部是由 Node 类型的数组实现的。 Node 包含着键值对,内部有四个字段,从 next 字段我们可以看出, N…

    技术杂谈 2023年7月24日
    078
  • 小爱音响PC蓝牙方式连接配置

    直接连接是连接不上的,需要在小爱音响APP上进行如下配置,打开下面的配置 “音箱蓝牙可被发现”后,PC的蓝牙再去搜索,即可连上的同时,安装蓝牙音响的驱动。 …

    技术杂谈 2023年5月31日
    0276
  • 【新特性速递】卡片式表格,Yeah~~~

    FineUI 的下个版本(v8.0.0),我们会为表格增加卡片样式,相信这是一个很多网友期待已久的功能。 网友的反馈 很久很久之前,就有网友在最初的 BBS 论坛提到这个事情,由于…

    技术杂谈 2023年6月1日
    0118
  • JAVA的变量与常量

    ; ; 实践是唯一的真理。 变量 变量的定义 变量就是可以变化的量。 JAVA变量是程序中最基础的程序单元,其要素包括变量名,变量类型及作用域。 写程序要注意程序的可读性 如图所示…

    技术杂谈 2023年6月21日
    0121
  • 如何管理分布式团队

    如何管理分布式团队 如今,寻找和雇用所有必要的人才来建立你的数字产品是具有挑战性的。因此,许多企业选择替代解决方案,并将其项目的某些部分外包。因此,他们可以扩大专业知识,实现更大的…

    技术杂谈 2023年6月1日
    087
  • Pthread并发编程(一)——深入剖析线程基本元素和状态

    Pthread 并发编程(一)——深入剖析线程基本元素和状态 前言 在本篇文章当中讲主要给大家介绍 pthread 并发编程当中关于线程的基础概念,并且深入剖析进程的相关属性和设置…

    技术杂谈 2023年7月24日
    069
  • Dijkstra算法求最短路

    例题链接 Dijkstra算法是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。其主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的…

    技术杂谈 2023年6月21日
    092
  • 职场感悟

    ============================================================================== 本博客已经废弃,不在维…

    技术杂谈 2023年6月1日
    092
  • Qt学习笔记

    联系方式 QQ: 2653728884 ,加Q请注明添加原因! Original: https://www.cnblogs.com/arminker/p/5121596.htmlA…

    技术杂谈 2023年7月11日
    069
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球