【问题标题】:How to input multiple parameters into an enum constructor?如何将多个参数输入到枚举构造函数中?
【发布时间】:2021-09-27 05:36:38
【问题描述】:

对于一个练习,我正在编写一个初始化单个虚拟扑克牌的程序,并且我还使用枚举作为主类,如下所示。

问题是这里的这个块

在下面的代码块中,我尝试将西装和排名都输入到这个变量中,但 Intellij 说输入“Jack”,因为西装不是陈述。Error Message "not a statement"(it's under "Jack").

 public static void main(String[] args)
    {
        CardMaker Card = (Hearts, "Jack");
        Card.printCard();
    }

代码:

import java.util.Arrays;
public enum CardMaker
{
    Hearts, Spades, Clubs, Diamond;
    CardMaker Suit;
    String[] Ranks = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King", "Ace"};
    String Rank = "";
    CardMaker(CardMaker Suit, String Rank)
    {
        this.Rank = Rank;
        this.Suit = Suit;
        if(Arrays.binarySearch(Ranks, Rank) < 0)
        {
            System.out.println("Invalid Rank try again");
            System.exit(1);
        }
    }
    private String[] Card = {String.valueOf(Suit), Rank};

    CardMaker()//This stops a error I forgot which one
    {

    }

    private String printCard()
    {
        System.out.printf("Here's your card '%1$s" ,Card.toString());
        return Card.toString();
    }

    public static void main(String[] args)
    {
        CardMaker Card = (Hearts, "Jack");
        Card.printCard();
    }


}

https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html 教程告诉我枚举构造函数是如何工作的,但第一次并没有告诉我你不能创建枚举的对象。

第二,它没有说你不能初始化一个枚举类型的对象(请解释它是如何工作的以及它是否与我的问题有关)。

(这不是一个骗局,因为这是我在 java 中为这个项目提出的同一种问题,但与 c# 不同,我忽略了其他语言,因为这是一个 java 语法问题)

【问题讨论】:

标签: java intellij-idea enums


【解决方案1】:

这行代码(来自您问题中的图片)不是有效的 Java 语法。

CardMaker Card = (Hearts, "Jack");

我假设你想创建一个CardMaker 对象,因此你需要调用构造函数,如

CardMaker Card = new CardMaker(Hearts, "Jack");

但是,当我相应地更改您的代码时,我收到以下 [编译器] 错误:

Cannot instantiate the type CardMaker

那是因为你不能创建枚举的实例。您只能声明一个类型为枚举类型的变量,并将其分配给枚举值之一。这就是枚举的全部目的——确保您不会分配无效值。

尽管如此,你的枚举看起来很奇怪。为什么它包含一个类型为相同枚举的成员?

我建议使用两个枚举:一个用于西装,另一个用于排名。

public enum Suit {
    CLUBS, DIAMONDS, HEARTS, SPADES;
}

public enum Rank {
    TWO,
    THREE,
    FOUR,
    FIVE,
    SIX,
    SEVEN,
    EIGHT,
    NINE,
    TEN,
    JACK,
    QUEEN,
    KING,
    ACE;

    public int getValue() {
        return ordinal() + 2;
    }
}

请注意,枚举 Rank 使用一种 hack 来使 Rank 的值与卡的实际值匹配。参考How can a Java enum start with 1

最后,CardMake 类包含两个成员:一个类型为Suit,另一个类型为Rank。 (代码后有更多注释。)

public class CardMake {
    private Rank rank;
    private Suit suit;

    public CardMake(Suit suit, Rank rank) {
        this.rank = rank;
        this.suit = suit;
    }

    public boolean equals(Object obj) {
        boolean areEqual = false;
        if (obj instanceof CardMake) {
            CardMake other = (CardMake) obj;
            areEqual = suit.ordinal() == other.suit.ordinal()  &&  rank.ordinal() == other.rank.ordinal();
        }
        return areEqual;
    }

    public int hashCode() {
        return suit.ordinal() * 10 + rank.getValue();
    }

    public String toString() {
        return String.format("%s of %s", rank, suit);
    }

    public static void main(String[] args) {
        CardMake card = new CardMake(Suit.HEARTS, Rank.JACK);
        System.out.printf("Here's your card: %s%n" ,card);
    }
}

现在,您无法创建具有无效排名的CardMake 实例,因此无需在类CardMake 的构造函数中检查该参数。

您需要重写方法toString(),因为如果您不这样做,它将使用超类(即java.lang.Object)中的方法,该方法返回类似于以下内容的字符串。

CardMake@1f

我还假设您可能想要检查两张卡是否相等,因此我添加了方法equals(它也覆盖了超类方法)。如果要覆盖方法equals,建议也覆盖方法hashCode(同样在超类中,即java.lang.Object)。

方法printf中的格式字符串不需要1$,尤其是在只有一个参数的情况下。请参阅 javadoc 了解类 java.util.Formatter

您不需要显式调用方法toString,方法printf 会为您完成。

最后也推荐使用Java naming conventions

运行上述代码会产生以下输出。

Here's your card: JACK of HEARTS

请注意,如果您希望值为 Jack 而不是 JACK(例如),则可以在任一(或两者)枚举中覆盖方法 toString

【讨论】:

    【解决方案2】:

    我已经重写了你的类和枚举。你应该这样做。 而且您对枚举的理解是不正确的。正如您可以想到的命名常量的枚举。您不能将数据变量和函数放在枚举中。


    enum Suit {
            Hearts,
            Spades,
            Clubs,
            Diamond
    }
    
    enum Rank {
            ONE,
            TWO,
            THREE,
            FOUR,
            FIVE,
            SIX,
            SEVEN,
            EIGHT,
            NINE,
            TEN,
            Jack,
            Queen,
            King,
            Ace
    }
    
    class CardMaker {
            Suit name;
            Rank rank;
    
            public CardMaker(final String cardName, final String cardRank) {
                    this.name = Suit.valueOf(cardName);
                    this.rank = Rank.valueOf(cardRank);
            }
    
            @Override
            public String toString() {
                    return "Name : " + name + " rank : " + rank;
            }
    }
    
    class Scratch {
            public static void main(String[] args) {
                    CardMaker card = new CardMaker(Suit.Hearts.name(), Rank.ONE.name());
                    System.out.println(card);
            }
    }
    

    【讨论】:

    • 您确实应该遵循 Java 命名约定。包含枚举类型的类名应该用 PascalCase 编写,所以 CARD_NAMECARD_RANK 应该分别是 CardNameCardRank,或者更好的是 SuitRank。枚举常量应该写成 UPPER_SNAKE_CASE,所以Hearts 应该是HEARTS,等等。
    • 据我所知,没有一张卡。我认为您需要从 CARD_RANK 枚举中删除它。
    • @MCEmperor 感谢您的建议。是的,我应该使用大写蛇形而不是全部大写。
    • 所以我应该使用类和枚举作为类型
    • 如果我这样做了,它会解决我的问题,因为枚举不能有对象
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-20
    • 2012-10-29
    • 2014-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多