为什么这些 Java 枚举的值会改变?

发布于 2024-07-29 02:45:23 字数 1649 浏览 1 评论 0原文

我在根据 enum 上的条件创建对象列表时遇到一些问题。 看来我完成列表后,列表中的每一项都相当于最后一项。

这是不同引用指向同一对象的经典情况,但我不知道如何避免它:

我在保持可读性的同时尽可能地减少了内容:

public class Foo {
  Digit[] array = new Digit[2];
  ArrayList<Foo> foozlets;

  Foo() {
    array[0] = Digit.ZERO;
    foozlets = new ArrayList<Foo>();
  }

  Foo(Foo old, Digit num) {
    this.array = old.array;  \\This line is a problem, what should it say?
    array[1] = num;
  }

  public static void main(String[] args) {
    Foo f = new Foo();
    System.out.println("Initial Foo:");
    System.out.println(f);
    f.listFoozlets();
  }

  void listFoozlets() {
    for (Digit k : Digit.values()) {
      if (k == Digit.TWO || k == Digit.FIVE) {
        foozlets.add(new Foo(this, k));
        System.out.println("** Foozlet being added **");
        Foo foo = new Foo(this, k);
        System.out.println(foo);
      }
    }
    System.out.println("** List of Foozlets **");
    for (Foo foo : foozlets) {
        System.out.println(foo);
    }
  }

  public String toString() {
    return array[0].toString() + " " + array[1].toString();
  }
}

enum Digit { ZERO, ONE, TWO, THREE, FOUR, FIVE }

这是输出:

Initial Foo:
ZERO NULL
** Foozlet being added **
ZERO TWO
** Foozlet being added **
ZERO FIVE
** List of Foozlets **
ZERO FIVE
ZERO FIVE

如果有人可以解释为什么列表中 Foo 的第一个实例发生变化,以及如何制作一个不改变的列表,我将不胜感激。

编辑:好的,我知道问题出在哪里了。 在真正的、更大的程序中,我有一个更大的数组,并且我想在为列表创建新的 Foo 时保留旧信息。 我更改了代码以反映有我想要维护的其他信息。 我该如何实现这个目标?

编辑 2021: 十二年后,我想到了这个,这是我的第一个 SO 问题。 如果这对您有帮助,我很高兴。 如果你想知道我到底想做什么,答案是“我不知道”。

I'm having some trouble with making list of objects based on a condition on an enum. It seems that after I have completed the list, every item in the list is equivalent to the last item.

It's the classic case of different references pointing to the same object, but I don't know how to avoid it:

I've pared things down as much as I can while maintaining readability:

public class Foo {
  Digit[] array = new Digit[2];
  ArrayList<Foo> foozlets;

  Foo() {
    array[0] = Digit.ZERO;
    foozlets = new ArrayList<Foo>();
  }

  Foo(Foo old, Digit num) {
    this.array = old.array;  \\This line is a problem, what should it say?
    array[1] = num;
  }

  public static void main(String[] args) {
    Foo f = new Foo();
    System.out.println("Initial Foo:");
    System.out.println(f);
    f.listFoozlets();
  }

  void listFoozlets() {
    for (Digit k : Digit.values()) {
      if (k == Digit.TWO || k == Digit.FIVE) {
        foozlets.add(new Foo(this, k));
        System.out.println("** Foozlet being added **");
        Foo foo = new Foo(this, k);
        System.out.println(foo);
      }
    }
    System.out.println("** List of Foozlets **");
    for (Foo foo : foozlets) {
        System.out.println(foo);
    }
  }

  public String toString() {
    return array[0].toString() + " " + array[1].toString();
  }
}

enum Digit { ZERO, ONE, TWO, THREE, FOUR, FIVE }

Here is the output:

Initial Foo:
ZERO NULL
** Foozlet being added **
ZERO TWO
** Foozlet being added **
ZERO FIVE
** List of Foozlets **
ZERO FIVE
ZERO FIVE

If someone can explain why the first instance of Foo on the list changes, and how I can make a list that doesn't change, I'd be grateful.

EDIT: Ok, I see where the problem is now. In the real, much larger program, I have a much larger array, and I want to keep the old information when I create a new Foo for the list. I've changed the code to reflect that there is additional information that I want to maintain. How do I accomplish this?

EDIT 2021: Wandered upon this, one of my first SO questions, twelve years later. If this helped you, I'm glad for that. If you are wondering what in the world I was trying to do, the answer is "I have no idea."

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

明明#如月 2024-08-05 02:45:23

这一点就是罪魁祸首:

Foo(Foo old, Digit num) {
  this.array = old.array;
  array[0] = num;
}

您将引用复制到旧的 Foo 数组,然后更改该数组中的值。

为什么你有一个大小为 1 的数组而不是一个 Digit ? 如果您确实想要该数组,您可能想要克隆它,而不仅仅是复制引用,但我们无法真正判断其意图是什么。

这是一个较短的示例:

enum Digit { ZERO, ONE, TWO, THREE, FOUR, FIVE }

public class Foo {
  Digit[] array = new Digit[1];

  Foo() {
    array[0] = Digit.ZERO;
  }

  Foo(Foo old, Digit num) {
    this.array = old.array;
    array[0] = num;
  }

  public String toString() {
    return array[0].toString();
  }

  public static void main(String[] args) {
    Foo f = new Foo();
    System.out.println(f);
    Foo other = new Foo(f, Digit.ONE);
    System.out.println(f);
  }
}

This bit is the culprit:

Foo(Foo old, Digit num) {
  this.array = old.array;
  array[0] = num;
}

You're copying a reference to the old Foo's array, and then changing the value in that array.

Why do you even have an array of size 1 instead of just a Digit? If you really want the array, you possibly want to clone it instead of just copying the reference, but we can't really tell what the intention is.

Here's a shorter example:

enum Digit { ZERO, ONE, TWO, THREE, FOUR, FIVE }

public class Foo {
  Digit[] array = new Digit[1];

  Foo() {
    array[0] = Digit.ZERO;
  }

  Foo(Foo old, Digit num) {
    this.array = old.array;
    array[0] = num;
  }

  public String toString() {
    return array[0].toString();
  }

  public static void main(String[] args) {
    Foo f = new Foo();
    System.out.println(f);
    Foo other = new Foo(f, Digit.ONE);
    System.out.println(f);
  }
}
oО清风挽发oО 2024-08-05 02:45:23

在第二个构造函数中:

Foo(Foo old, Digit num) {
  this.array = old.array;
  array[0] = num;
}

您正在重复使用 old 中的列表。 您想要创建该列表的副本而不是使用相同的列表。 您可以通过将分配更改为:

Foo(Foo old, Digit num) {
  this.array = new ArrayList<Foo>(old.array);
  array[0] = num;
}

In your second constructor:

Foo(Foo old, Digit num) {
  this.array = old.array;
  array[0] = num;
}

You are re-using the list from old. You want to create a copy of that list rather than using the same list. You can do that by changing the assignment to:

Foo(Foo old, Digit num) {
  this.array = new ArrayList<Foo>(old.array);
  array[0] = num;
}
单身情人 2024-08-05 02:45:23

问题似乎出在这一行:

    this.array = old.array;

您正在共享数组引用,因此每个 Foo 共享相同的数组,因此它们在 array[0] 处都有相同的值。

要解决此问题,请尝试:

  this.array = old.array.clone();

The problem appears to be in this line:

    this.array = old.array;

You are sharing array references, so every Foo shares the same array, so they all have the same value at array[0].

To fix this, try:

  this.array = old.array.clone();
画中仙 2024-08-05 02:45:23

本例中的对象引用是数组。 foo 的构造函数是您遇到问题的地方,具体来说:

Foo(Foo old, Digit num) {
   this.array = old.array; // reference the old array 
   array[0] = num; // set the first element of the array (for this AND the old array) to num
}

您需要将数组复制到 foo 构造函数中的新数组。

The object reference in this case is the array. The constructor of foo is where you're having the issue, specifically:

Foo(Foo old, Digit num) {
   this.array = old.array; // reference the old array 
   array[0] = num; // set the first element of the array (for this AND the old array) to num
}

You need to copy the array to a new array in the constructor of foo.

太阳公公是暖光 2024-08-05 02:45:23

而不是

Foo(Foo old, Digit num) {
  this.array = old.array;
  array[0] = num;
}

简单地执行

Foo(Foo old, Digit num) {
  array[0] = num;
}

如果您确实需要数组, ...
(最好是使用另一个回复中建议的简单数字)

Instead of

Foo(Foo old, Digit num) {
  this.array = old.array;
  array[0] = num;
}

simply do

Foo(Foo old, Digit num) {
  array[0] = num;
}

if you really need the array at all...
(best would be to use a simple Digit as suggested in another reply)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文