Kotlin / Java 在类型为 Int 的 switch 语句中使用枚举。

huangapple go评论106阅读模式
英文:

Kotlin / Java use enum in a switch statement of type Int

问题

对于一个Android项目,我有一个 .kt 文件:

class foo () {
    enum class animal (var Id: Int) {
        CAT(0),
        DOG(1),
        FISH(2),
    }
}

还有一个 .java 文件,在这里出现了问题:

public void processAnimal(int animalId) {
    switch(animalId) {
        case foo.animal.CAT.Id:
            //做一些事情
            break;
        case foo.animal.DOG.Id:
            //做其他一些事情
            break;
        case foo.animal.FISH.Id:
            //做一些奇怪的事情
            break;
    }
}

.Id 上它会给出一个错误,指出 'Id 在 foo.animal 中具有私有访问权限',所以这样不起作用。

.Id 更改为 .getId() 会因为 switch 语句而出现 '需要常量表达式' 的错误。

对于签名 public void processAnimal(int animalId) {,将类型设为 int 而不是 animal 是一个我无法控制的要求,如果不是这样,这将是正确的解决方案。

在 .kt 文件中将字段标记为 public 不会改变任何内容。

有没有办法实现我要做的事情?

谢谢!

英文:

For an Android project, I have a .kt file:

class foo () {
    enum class animal (var Id: Int) {
        CAT(0),
        DOG(1),
        FISH(2),
    }
}

And a .java file, where the problem occurs:

public void processAnimal(int animalId) {
    switch(animalId) {
        case foo.animal.CAT.Id:
            //do something
            break;
        case foo.animal.DOG.Id:
            //do something else
            break;
        case foo.animal.FISH.Id:
            //do something fishy
            break;
    }
}

On the .Id it gives an error 'Id has private access in foo.animal', so that does not work.

Changing .Id to .getId() gives 'Constant expression required' because of the switch statement.

It is a requirement out of my control for the type to be int instead of animal in the signature public void processAnimal(int animalId) { and this would be the correct solution if it were not out of my control.

Marking fields as public in the .kt file changes nothing.

Is there a way to achieve what I am setting out to do?

Thank you!

答案1

得分: 8

因为 Java 的 switch 语句的限制,我所能想到的唯一解决方法是在枚举类本身中创建一个帮助函数,允许我们将那个 Id 转换为枚举 Value

Java 函数如下:

public void processAnimal(int animalId) {
    AnimalEnum animalEnum = AnimalEnum.fromInt(animalId);
    switch(animalEnum) {
        case CAT:
            //做一些事情
            break;
        case DOG:
            //做另一些事情
            break;
        case FISH:
            //做一些奇怪的事情
            break;
    }
}

枚举类可能如下所示:

enum AnimalEnum(val Id: Int) { 
    CAT(0),
    DOG(1),
    FISH(2);

    companion object {
        @JvmStatic //使其从 Java 中可访问
        fun fromInt(givenInt: Int): AnimalEnum {
            return when (givenInt) {
                CAT.Id -> CAT
                DOG.Id -> DOG
                FISH.Id -> FISH
                else -> throw Exception("无效的 id `$givenInt`,可用的 id 为 ${values().map { it.Id }}") 
            }
        }
    }
}

fromInt() 函数的另一种方式如下:

companion object {
    private val map = values().associateBy(AnimalEnum::Id)
    @JvmStatic //使其从 Java 中可访问
    fun fromInt(givenInt: Int) = map[givenInt] ?: throw Exception("无效的 id `$givenInt`,可用的 id 为 ${values().map { it.Id }}")
}

第二个选项不太易读,但在有大量枚举值的情况下更为合适。

英文:

The only way I can think of making this work (due to the java switch limitations) is to create a helper function in the enum class itself that will allow us to translate that Id into an enum Value.

The java function would be:

public void processAnimal(int animalId) {
	AnimalEnum animalEnum = AnimalEnum.fromInt(animalId);
	switch(animalEnum) {
		case CAT:
			//do something
			break;
		case DOG:
			//do something else
			break;
		case FISH:
			//do something fishy
			break;
	}
}

And the enum class would look something like this:

enum class AnimalEnum(val Id: Int) { //classes should start with an uppercase letter in kotlin
CAT(0),
DOG(1),
FISH(2);

companion object {
	@JvmStatic //to be accessible from java
	fun fromInt(givenInt: Int): AnimalEnum {
		return when (givenInt) {
			CAT.Id -> CAT
			DOG.Id -> DOG
			FISH.Id -> FISH
			else -> throw Exception("Invalid id `$givenInt`, available ids are ${values().map { it.Id }}") // or a null or something
		}
	}
}}

Another way of writing that fromInt() function would be:

companion object {
    private val map = values().associateBy(AnimalEnum::Id)
    @JvmStatic //to be accessible from java
    fun fromInt(givenInt: Int) = map[givenInt] ?: throw Exception("Invalid id `$givenInt`, available ids are ${values().map { it.Id }}") // or a null or something
}

The second option is not as readable, but better if we have a lot of enum values

huangapple
  • 本文由 发表于 2020年10月2日 12:17:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/64166099.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定