【问题标题】:How do I use an enum copy constructor in Java?如何在 Java 中使用枚举复制构造函数?
【发布时间】:2011-12-15 10:49:57
【问题描述】:

我正在尝试完成一个项目,虽然我已经尝试过,但我似乎无法做到这一点。这是枚举:

public enum Symbols {
    /**
     * The Seven
     */
    SEVEN(12,"images/seven.jpg"),
    /**
     * The Watermelon
     */
    WATERMELON(10,"images/watermelon.jpg"),
    /**
     * The Orange
     */
    ORANGE(8,"images/orange.jpg"),
    /**
     * The Plum
     */
    PLUM(6,"images/plum.jpg"),
    /**
     * The Lemon
     */
    LEMON(4,"images/lemon.jpg"),
    /**
     * The Cherry
     */
    CHERRY(2,"images/cherry.jpg");

    private int payout;             // Symbol payout value
    private BufferedImage image;    // Symbol image
    private String icon;            // Symbol file name

    /** Constructor - Payout must be positive and even, file name must not be null
     * @param payout - Symbol payout amount
     * @param icon - Symbol image file name
     */
    Symbols(int payout, String icon){
        this.payout = payout;
        this.icon = icon;
        loadImage(icon);
    }

    /** Copy Constructor - Symbol must not be null
     * @param s - A single symbol
     */
    Symbols(Symbols s){
        payout = s.payout;
        icon = s.icon;
        loadImage(icon);
    }

现在我可以进入 main 并创建一个名为“s”的符号,如下所示:

Symbols s = Symbols.CHERRY;

但是我在使用给定的复制构造函数复制“s”时遇到了麻烦:

Symbols t = Symbols(s);

如果我尝试这样做,我会收到错误消息:“方法 Symbols(Symbols) 未为 Symbols 类型定义。”

谢谢

【问题讨论】:

    标签: java enums copy copy-constructor


    【解决方案1】:

    好吧,您需要将其公开,但它仍然无法正常工作。 Java 中没有复制构造函数;你不能“新建”一个枚举,这是下一个错误;并且在任何情况下,Java 都会竭尽全力确保每个 JVM 的每个枚举值只有一个副本。你认为你需要一个拷贝构造函数究竟是为了什么?

    解决方案:

    Symbols s = Symbols.CHERRY;
    Symbols t = s;
    

    【讨论】:

    • 好吧,如果你定义了复制构造函数(他已经完成了)。
    • @MarkPeters 但编译器不会使用它们,除非你自己调用它们。例如,他给出的代码不会编译,如果他写了t = s;,编译器就不会自动调用复制构造函数。我不称其为复制构造函数。只是一个构造函数。
    • 你是对的,它不是复制构造函数,因为存在隐式调用它的语法(就像我想 C++ 那样)。但我认为将一个构造函数称为“复制构造函数”仍然是常见的做法。
    • @MarkPeters 我无法帮助别人做什么;-)
    【解决方案2】:

    枚举应该是一个不可变的集合——你不应该能够创建新的。并且构造函数被强制为私有(即使没有标记为私有)。

    由于它们是不可变的,因此您始终应该保证,如果您有 Symbols.CHERRY 对象的实例,它始终是同一个实例,因此您可以执行诸如测试对象等价性而不是等价性之类的事情 - 即您可以做

    if (symbol == CHERRY) 
    

    而不是

    if (symbol.equals(CHERRY))
    

    因为如果你必须使用 CHERRY,它们肯定是同一个对象。

    这更倾向于成为Typesafe Enum 模式的强制版本:

    public class Suit {
        private final String name;
    
        public static final Suit CLUBS =new Suit("clubs");
        public static final Suit DIAMONDS =new Suit("diamonds");
        public static final Suit HEARTS =new Suit("hearts");
        public static final Suit SPADES =new Suit("spades");    
    
        private Suit(String name){
            this.name =name;
        }
    }
    

    【讨论】:

      【解决方案3】:

      好吧,构造函数只会在你调用 new 关键字时被调用:

      Symbols t = new Symbols(s);
      

      如果没有 new,它会认为您正在尝试调用名为 Symbols 的方法。

      但这在这种情况下无关紧要,因为您无法在常量定义之外实例化枚举。如果可以,它不会是枚举。

      让我们检查一下为什么您曾经想要拥有一个枚举的副本。如果您需要副本,那一定是因为您说枚举是有状态的,这一定不是真的。枚举必须是不可变的。由于它们必须是不可变的,因此您可以在任何地方共享实例。

      【讨论】:

        【解决方案4】:

        你使用 ENUM 是这样的:

        public enum Symbols {
            SEVEN(12,"images/seven.jpg"),
            WATERMELON(10,"images/watermelon.jpg");
        
            private int payout;
            private String icon;
        
            Symbols(int payout, String icon){
                this.payout = payout;
                this.icon = icon;
            }
        
            public int getPayout(){
                return this.payout;
            }
        
            public String getIcon(){
                return this.icon;
            }
            public static void main(String[] args){
                System.out.println(Symbols.SEVEN.getPayout());
            }
        }
        

        其他答案很好地解释了为什么不能拥有复制构​​造函数。基本上,枚举类的“实例”(SEVEN 和 WATERMELON)是不可变的,因此您不能在运行时在其中指定任何其他值,也不能创建新值。

        【讨论】:

          【解决方案5】:

          枚举不是普通的类。您不能手动构建它们。枚举“类”本身基本上是一个“抽象”类。每个值都被实现为枚举“类”的一个单独的特定子类。

          【讨论】:

            【解决方案6】:

            枚举是不允许创建新对象的类。所以你的 Symbol 类(枚举)只有六个实例。您不能调用枚举构造函数,但可以拥有为六个实例创建的引用的副本。

            Symbols s = Symbols.CHERRY; //Get a copy of reference for instance CHERRY
            

            另一方面,如果你想在 Java 中创建一个高大的构造函数,你需要使用关键字“new”。

            【讨论】:

              猜你喜欢
              • 2016-07-17
              • 2011-08-20
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-04-18
              • 1970-01-01
              相关资源
              最近更新 更多