【问题标题】:Constant Variables in JavaJava中的常量变量
【发布时间】:2016-04-21 21:06:45
【问题描述】:

我正在像这样的类中创建一些静态对象。我希望它们保持不变,但似乎我做错了,因为所有对象 a b c 都是相同的(它们的 x 是相同的)。谁能解释为什么?

public class Key {
private Note[] sequence;
private String name;

public Key() {
    this.sequence = Note.NOTES;
}

public Key(String name, Note[] notes) {
    this.sequence = Note.NOTES;
    this.name = name;
    for(int i = 0; i < this.sequence.length; i++){
        for(int j = 0; j < notes.length; j++){
            if(this.sequence[i].equals(notes[j])){
                this.sequence[i].setIntensity(0.6);
                break;
            }
            else this.sequence[i].setIntensity((double)0);
        }
    }
}

private static final Key C = new Key("C", new Note[]{Note.F2, Note.G2, Note.A2, Note.B2, Note.C3, Note.D3, Note.E3, Note.F3, Note.G3, Note.A3, Note.B3});
private static final Key CSharp = new Key("C#", new Note[]{Note.Fsharp2, Note.Gsharp2, Note.Asharp2, Note.C3, Note.Csharp3, Note.Dsharp3, Note.F3, Note.Fsharp3, Note.Gsharp3, Note.Asharp3});
private static final Key D = new Key("D", new Note[]{Note.Fsharp2, Note.G2, Note.A2, Note.B2, Note.Csharp3, Note.D3, Note.E3, Note.Fsharp3, Note.G3, Note.A3, Note.B3});
private static final Key EFlat = new Key("Eb", new Note[]{Note.F2, Note.G2, Note.Gsharp2, Note.Asharp2, Note.C3, Note.D3, Note.Dsharp3, Note.F3, Note.G3, Note.Gsharp3, Note.Asharp3});
private static final Key E = new Key("E", new Note[]{Note.Fsharp2, Note.Gsharp2, Note.A2, Note.B2, Note.Csharp3, Note.Dsharp3, Note.E3, Note.Fsharp3, Note.Gsharp3, Note.A3, Note.B3});
private static final Key F = new Key("F", new Note[]{Note.F2, Note.G2, Note.A2, Note.Asharp2, Note.C3, Note.D3, Note.E3, Note.F3, Note.G3, Note.A3, Note.Asharp3});
private static final Key FSharp = new Key("F#", new Note[]{Note.Fsharp2, Note.Gsharp2, Note.Asharp2, Note.B2, Note.Csharp3, Note.Dsharp3, Note.F3, Note.Fsharp3, Note.Gsharp3, Note.Asharp3, Note.B3});
private static final Key G = new Key("G", new Note[]{Note.Fsharp2, Note.G2, Note.A2, Note. B2, Note.C3, Note.D3, Note.E3, Note.Fsharp3, Note.G3, Note.A3, Note.B3});
private static final Key GSharp = new Key("G#", new Note[]{Note.F2, Note.G2, Note.Gsharp2, Note.Asharp2, Note.C3, Note.Csharp3, Note.Dsharp3, Note.F3, Note.G3, Note.Gsharp3, Note.Asharp3});
private static final Key A = new Key("A", new Note[]{Note.Fsharp2, Note.Gsharp2, Note.A2, Note.B2, Note.Csharp3, Note.Dsharp3, Note.E3, Note.Fsharp3, Note.Gsharp3, Note.A3, Note.B3});
private static final Key BFlat = new Key("Bb", new Note[]{Note.F2, Note.G2, Note.A2, Note.Asharp2, Note.C3, Note.D3, Note.Dsharp3, Note.F3, Note.G3, Note.A3, Note.Asharp3});
private static final Key B = new Key("B", new Note[]{Note.Fsharp2, Note.Gsharp2, Note.Asharp2, Note.B2, Note.Csharp3, Note.Dsharp3, Note.E3, Note.Fsharp3, Note.Gsharp3, Note.Asharp3, Note.B3});
}

【问题讨论】:

  • 没有。 x 的值会有所不同。你在哪里试过打印这些?
  • 我确实简化了我的代码,但我认为它完全一样。我不知道为什么,但它使所有属性都变得相同
  • 向我们展示完整的代码。
  • 到底发生了什么?
  • 所有静态对象的属性顺序相同。他们取最后一个对象(Key.B)的值

标签: java static instance


【解决方案1】:

您的代码创建具有不同值的不同对象,但它们不是常量

要创建一个constant,你需要将变量声明为final,另外你需要阻止任何改变它的可能性,使对象不可变。在这种情况下,可以完成 final 的所有字段。 更一般地,要创建不可变类,您需要遵循一些规则:

  • 不要添加任何setter方法

  • 将所有字段声明为 final 和 private

  • 如果字段是可变对象,则为 getter 方法创建其防御性副本

  • 如果传递给构造函数的可变对象必须分配给字段,请创建它的防御性副本

  • 不允许子类覆盖方法。

如果你喜欢关于不可变对象的一些额外信息,我写了一篇关于 DZone 的文章,你可以在以下地址找到 link

所以对于你的代码:

final Class A {
    final int x;

    public A(int x) {
        this.x = x;
    };

    private final static A a = new A(1);
    private final static A b = new A(2);
    private final static A c = new A(3);
}

回答最后一条评论。

在你的构造函数中你有:

public Key(String name, Note[] notes) {
    this.sequence = Note.NOTES;
    ...
}

这意味着sequence 的值对Key 的所有实例都是通用的。如果您需要不同的序列值,则需要执行类似操作(基本上是克隆数组 Note.NOTES)

public Key(String name, Note[] notes) {
    this.sequence = Note.NOTES.clone();
    ...
}

【讨论】:

  • 它不起作用。实际上,我试图简化我的代码。我会将帖子编辑为我的完整代码
  • 您之前的示例正在运行。此外,这个新代码似乎有效,但我没有运行它。尝试打印名称。如果它们不同,它会起作用。也许你的 for 循环会根据你的喜好以不同的方式工作,但数据不一样,也许它们是相等的(这意味着相同的值,不同的引用)
  • 我尝试分别创建这些对象(即我只创建了 Key.C)并且它们中的每一个都给出了不同的值。当我像上面一样将它们组合在一起时,它们的名称仍然不同,只是序列属性变得相同(并且它们取最后一个对象的值:Key.B)
  • 所以问题不在于它们在引用方面没有不同。问题是它们在价值方面是相等的。所以从技术上讲,问题出在你的 for 循环中(原始问题中不存在)
  • 我打印出每个对象的序列(这是一个数组)。它为所有对象显示@78308db1。这是否意味着它是相同的参考?我太糊涂了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-13
  • 1970-01-01
  • 2011-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-06
相关资源
最近更新 更多