如何正确地将字符串与枚举值进行比较?

68

作业: 石头剪刀布游戏。

我创建了一个枚举:

      enum Gesture{ROCK,PAPER,SCISSORS};

我想比较值以决定谁赢——计算机还是人类。设定值完全没有问题,比较也能正常进行(布包石头,石头压剪刀,剪刀剪布)。然而,我无法让平局起作用。无论何时出现平局,用户都被宣布为赢家。

啊啊啊...这会澄清一些事情:userPick 是一个带有 rockpaperscissors 值的 String。我无法使用 == 来比较 userPick 和下面你可以看到被转换为类型 GesturecomputerPick 枚举。

      if(computer == 1)
         computerPick = Gesture.ROCK;
      else
         if(computer == 2)
           computerPick = Gesture.PAPER;
         else
           computerPick = Gesture.SCISSORS;
      if(userPick.equals(computerPick))
       {
          msg = "tie";
          ++tieGames;
       }
           etc....

我猜测问题出在rockROCK不相等,或者String userPick无法与Gesture computerPick匹配,因为后者不是String。然而,在我的教科书或Oracle的Java教程中找不到类似情况的示例,所以我不确定如何解决这个问题...

有什么提示吗?


4
没错,你不能将字符串 "rock" 与枚举类型 Gesture.ROCK 进行比较。你需要一种字符串到 Gesture 枚举的映射函数,这样才能比较两个枚举类型。幸运的是,Java 已经提供了这个函数。尝试使用 Gesture.valueOf([你的字符串])。如果我没记错的话,该函数是大小写敏感的。但我可能记错了。 - K Mehta
1
那个函数是大小写敏感的。谢谢! - Shahbaz Sheikh
使用 .toString() 方法将枚举转换为字符串,然后判断 Gesture.ROCK.toString().equals("ROCK") 不就可以了吗? - Badri Paudel
11个回答

68

从你的问题中我了解到userPick是一个String类型的值。你可以像这样进行比较:

if (userPick.equalsIgnoreCase(computerPick.name())) . . .

顺带一提,如果你确定computer始终只有123(没有其他值),你可以使用以下代码将其转换为Gesture枚举:

Gesture computerPick = Gesture.values()[computer - 1];

@Ted Hopp:非常好的回答,非常感谢。不过我有一个后续问题……computerPick末尾的.name是什么意思?我猜这是指向computerPick的特定实例的某个东西?我正在尝试理解这样做与if (userPick.equalsIgnoreCase(computerPick()))有何区别。谢谢! - dwwilson66
如果computerPick是类型为Gesture的枚举值,则computerPick().name()返回一个字符串,其中包含computerPick当前值的符号名称。 (也就是说,如果computerPick == Gesture.ROCK,则computerPick.name()将是字符串“ROCK”。(每个枚举类型都有由编译器生成的实例方法name()ordinal()。该类型还具有自动生成的静态方法values()valueOf(String)。请参见Java语言规范 - Ted Hopp
很好。谢谢。那讲得很清楚。当然,name()并没有包含在我的教科书中,它似乎更多地为可读性而放弃了细节....:\ - dwwilson66
我正在使用Java 8,当我选择.name()时,我看到这个 - 返回此枚举常量的名称,与其枚举声明中声明的完全相同。大多数程序员应该优先使用toString方法,因为toString方法可能返回更用户友好的名称。此方法主要设计用于特殊情况下的使用,其中正确性取决于获取确切的名称,这将不会因发布而变化。 返回: 此枚举常量的名称 - jmathewt

26

你应该在enum中声明toString()valueOf()方法。

 import java.io.Serializable;

public enum Gesture implements Serializable {
    ROCK,PAPER,SCISSORS;

    public String toString(){
        switch(this){
        case ROCK :
            return "Rock";
        case PAPER :
            return "Paper";
        case SCISSORS :
            return "Scissors";
        }
        return null;
    }

    public static Gesture valueOf(Class<Gesture> enumType, String value){
        if(value.equalsIgnoreCase(ROCK.toString()))
            return Gesture.ROCK;
        else if(value.equalsIgnoreCase(PAPER.toString()))
            return Gesture.PAPER;
        else if(value.equalsIgnoreCase(SCISSORS.toString()))
            return Gesture.SCISSORS;
        else
            return null;
    }
}

2
这是一个很好的例子,在Java 7中,valueOf方法已经在枚举中实现。它与您的示例相同。 - Evan
9
根据Java语言规范§8.9.2,每个enum类型的声明自动生成一个静态的 valueOf(String) 方法,其行为类似于您的方法(除了抛出异常而不是返回null并且区分大小写)。每个枚举常量还从Enum继承了name()方法,其行为类似于您的toString()(返回枚举常量的确切名称)。@Evan - valueOf自从Java引入枚举以来就一直属于Enum类,它并不是Java 7新增的。 - Ted Hopp
这对包含下划线并且需要进行比较的枚举非常有用......它确实帮助了我,谢谢您.... - Grim

10

我的想法:

public enum SomeKindOfEnum{
    ENUM_NAME("initialValue");

    private String value;

    SomeKindOfEnum(String value){
        this.value = value;
    }

    public boolean equalValue(String passedValue){
        return this.value.equals(passedValue);
    }
}

如果您想检查值,则可以编写:

SomeKindOfEnum.ENUM_NAME.equalValue("initialValue")

对我来说看起来不错 :). 也许有人会觉得它有用。


6
public class Main {

    enum Vehical{
        Car,
        Bus,
        Van
    }

    public static void main(String[] args){

      String vehicalType = "CAR";

        if(vehicalType.equals(Vehical.Car.name())){
            System.out.println("The provider is Car");
        }

     String vehical_Type = "BUS";

       if(vehical_Type.equals(Vehical.Bus.toString())){
            System.out.println("The provider is Bus");
        }


    }
}

5

定义枚举:

public enum Gesture
{
    ROCK, PAPER, SCISSORS;
}

定义一个方法来检查enum内容:

private boolean enumContainsValue(String value)
{
    for (Gesture gesture : Gesture.values())
    {
        if (gesture.name().equals(value))
        {
            return true;
        }
    }

    return false;
}

并使用它:

String gestureString = "PAPER";

if (enumContainsValue(gestureString))
{
    Gesture gestureId = Gesture.valueOf(gestureString);

    switch (gestureId)
    {
        case ROCK:
            Log.i("TAG", "ROCK");
            break;

        case PAPER:
            Log.i("TAG", "PAPER");
            break;

        case SCISSORS:
            Log.i("TAG", "SCISSORS");
            break;
    }
}

3
您可以采用更简单的方式,如下所示:
boolean IsEqualStringandEnum (String str,Enum enum)
{
  if (str.equals(enum.toString()))
     return true;
  else
     return false;
}

7
为什么不使用return str.equals(enum.toString()),然后为什么不直接使用这个表达式? - Dude
对于以'is'开头的方法,最好始终返回布尔值。 - Salvador Valencia

2

这是我在 Java 8 中的解决方案:

 public static Boolean isValidCity(String cityCode) {
        return Arrays.stream(CITY_ENUM.values())
                .map(CITY_ENUM::getCityCode)
                .anyMatch(cityCode::equals);
 }

0

进行手势类型的静态导入,然后使用valuesOf()方法可以使代码看起来更加简洁:

enum GestureTypes{ROCK,PAPER,SCISSORS};

并且

import static com.example.GestureTypes.*;
public class GestureFactory {

    public static Gesture getInstance(final String gesture) {
        if (ROCK == valueOf(gesture))
            //do somthing
        if (PAPER == valueOf(gesture))
            //do somthing
    }
}

0

这看起来很干净。

public enum Plane{

/**
 * BOEING_747 plane.
 */
BOEING_747("BOEING_747"),

/**
 * AIRBUS_A380 Plane.
 */
AIRBUS_A380("AIRBUS_A380"),

;

private final String plane;       

private Plane(final String plane) {
    this.plane= plane;
}

Plane(){ 
    plane=null; 
}


/**
 * toString method.
 * 
 * @return Value of this Enum as String.
 */
@Override
public String toString(){
   return plane;
}

/**
 * This method add support to compare Strings with the equalsIgnoreCase String method.
 * 
 * Replicated functionality of the equalsIgnorecase of the java.lang.String.class
 * 
 * @param value String to test.
 * @return True if equal otherwise false.
 */
public boolean equalsIgnoreCase(final String value){
    return plane.equalsIgnoreCase(value);
}

然后在主代码中:

String airplane="BOEING_747";

if(Plane.BOEING_747.equalsIgnoreCase(airplane)){
     //code
}

在我看来,你为了稍微改变行为而费尽了心思去重载枚举。 - Salvador Valencia

-1

你可以按如下方式将字符串与枚举项进行比较:

public class Main {

    enum IaaSProvider{
        aws,
        microsoft,
        google
    }

    public static void main(String[] args){

        IaaSProvider iaaSProvider = IaaSProvider.google;

        if("google".equals(iaaSProvider.toString())){
            System.out.println("The provider is google");
        }

    }
}

尝试在等于比较中使用这样的字符串可能不起作用。即使它能够工作,你也应该将其设置为一个变量。 - KHeaney
1
使用字符串值没有问题,虽然可能不太美观。而且,“google”.equals(...)也可以编译通过。 - Salvador Valencia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接