对比Java学Kotlin枚举

Posted 陈蒙_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对比Java学Kotlin枚举相关的知识,希望对你有一定的参考价值。

对比明细

对比项javakotlin
关键字enumenum class
可否实现接口
可否继承抽象类
可否存在抽象方法
可否创建成员方法
内置成员方法valueOf(String) & values()valueOf(String) & values()

使用方法示例

枚举常用于穷举类型相关的场景中,以四个方向为例,我们用Java代码表示如下:

enum Direction {
    NORTH, SOUTH, WEST, EAST
}

在 Kotlin 中怎么使用呢?稍微有点不同,需要加个 class 关键字:

enum class Direction {
    NORTH, SOUTH, WEST, EAST
}

不管是 Java 还是 Kotlin,都可以在枚举中有构造方法:
Java 形式:

enum Direction {
    Direction(int x, int y) {}
    NORTH(0, 1), SOUTH(0, -1), WEST(-1, 0), EAST(1, 0)
}

Kotlin 形式:

enum class Direction(val x: Int, val y: Int) {
    NORTH(0, 1),
    SOUTH(0, -1),
    WEST(-1, 0),
    EAST(1, 0)
}

除此之外,Kotlin 可以继承抽象类、接口,类体中可以声明抽象方法:

enum class Direction(val x: Int, val y: Int) : Runnable{
    NORTH(0, 1) { // 匿名类 NORTH
        override fun coordinate(): Pair<Int, Int> {
            TODO("Not yet implemented")
        }

        override fun run() {
            TODO("Not yet implemented")
        }
    },
    SOUTH(0, -1) { // 匿名类 SOUTH
        override fun coordinate(): Pair<Int, Int> {
            TODO("Not yet implemented")
        }

        override fun run() {
            TODO("Not yet implemented")
        }
    },
    WEST(-1, 0) { // 匿名类 WEST
        override fun coordinate(): Pair<Int, Int> {
            TODO("Not yet implemented")
        }

        override fun run() {
            TODO("Not yet implemented")
        }
    },
    EAST(1, 0) { // 匿名类 EAST
        override fun coordinate(): Pair<Int, Int> {
            TODO("Not yet implemented")
        }

        override fun run() {
            TODO("Not yet implemented")
        }
    };

    override fun run() {
        TODO("Not yet implemented")
    }

    abstract fun coordinate(): Pair<Int, Int> // 抽象方法
}

Java 的枚举可以实现接口,但是无法继承抽象类,也无法在自己的类体中声明抽象方法,只能声明一般的成员方法。同时在实现接口时:

public enum Direction implements Runnable {
    NORTH { // 匿名类 NORTH
        @Override
        public void run() {
            super.run();
        }

        @Override
        protected void memberFunc() {
            super.memberFunc();
        }
    },
    SOUTH { // 匿名类 SOUTH
        @Override
        public void run() {
            super.run();
        }

        @Override
        protected void memberFunc() {
            super.memberFunc();
        }
    },
    WEST { // 匿名类 WEST
        @Override
        public void run() {
            super.run();
        }

        @Override
        protected void memberFunc() {
            super.memberFunc();
        }
    },
    EAST { // 匿名类 EAST
        @Override
        public void run() {
            super.run();
        }

        @Override
        protected void memberFunc() {
            super.memberFunc();
        }
    };

    @Override
    public void run() { // 枚举实现 Runnable 接口 }
    
    protected void memberFunc() { // 枚举类自有普通成员函数 }
}

可以看出,不管是 kotlin 还是 Java,匿名类之间都是有逗号分割的,而最后一个匿名类和成员方法之间有分号分割。

常量相关方法

在 Kotlin 枚举中,有两个与常量相关的方法:

EnumClass.valueOf(value: String): EnumClass
EnumClass.values(): Array<EnumClass>

对于 valueOf() 方法,我们可以传入具体类的名称,即可获取相关的枚举类型类:

val v1 = Direction.valueOf("NORTH")
val v2 = Direction.valueOf("North") // 无该名称对应的枚举类型,抛出异常 “IllegalArgumentException: No enum constant Direction.North”

对于 values() 方法,我们可以使用该方法列举出所有枚举类型:

// 输出 NORTH, SOUTH, WEST, EAST
println(Color.values().joinToString())

或者使用更为通用的 enumValues() 方式:

enum class Direction { NORTH, SOUTH, WEST, EAST }

inline fun <reified T : Enum<T>> printAllValues() {
    print(enumValues<T>().joinToString { it.name })
}

printAllValues<Direction>() // prints NORTH, SOUTH, WEST, EAST

而且,每一个枚举常量里面都有两个成员变量:

val name: String // 枚举常量名称
val oridinal: Int // 该枚举常量在枚举类中声明的位置

参考文档

以上是关于对比Java学Kotlin枚举的主要内容,如果未能解决你的问题,请参考以下文章

对比Java学Kotlin枚举

对比Java学Kotlin单例模式

对比Java学Kotlin数据类

对比Java学Kotlin数据类

对比Java学Kotlin数据类

Kotlin系列之枚举类