Java中的常量变量

Java中的常量变量,java,static,instance,Java,Static,Instance,我正在这样的类中创建一些静态对象。我希望它们是常数,但似乎我做错了什么,因为所有对象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 = N

我正在这样的类中创建一些静态对象。我希望它们是常数,但似乎我做错了什么,因为所有对象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});
}
公共类密钥{
私人票据[]序列;
私有字符串名称;
公钥{
this.sequence=Note.NOTES;
}
公钥(字符串名称,注释[]注释){
this.sequence=Note.NOTES;
this.name=名称;
for(int i=0;i
您的代码使用不同的值创建不同的对象,但它们不是常量

要创建一个常量,您需要将变量声明为
final
,此外,还需要阻止任何更改它的可能性,使对象不可变。在这种情况下,可以使
最终
所有字段
。 一般来说,要创建不可变类,您需要遵循以下规则:

  • 不要添加任何setter方法

  • 声明所有字段为final和private

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

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

  • 不允许子类重写方法

如果你喜欢一些关于不可变对象的附加信息,我写了一篇关于DZone的文章,你可以在下面的

因此,对于您的代码:

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)


否。
x
的值将不同。你在哪里试过打印这些东西?我确实简化了我的代码,但我认为完全一样。我不知道为什么,但它使所有属性都变成了相同的显示完整代码。到底发生了什么?所有静态对象的属性序列都是相同的。它们取最后一个对象(Key.B)的值,它不起作用。实际上,我试图简化我的代码。我会将文章编辑成我的完整代码,你之前的例子是有效的。这个新代码似乎也能工作,但我没有运行它。试着打印名字。如果它们是不同的,它会起作用。可能for循环的工作方式与您所希望的不同,但数据不相同,可能它们相等(这意味着相同的值,而不是相同的引用)。我尝试分别创建这些对象(即,我只创建了Key.C),并且每个对象都给出了不同的值。当我如上所述将它们组合在一起时,它们的名称仍然不同,只有序列属性变得相同(并且它们采用最后一个对象的值:Key.B),所以问题不在于它们在引用方面没有不同。问题是他们在价值观上是平等的。从技术上讲,问题出在for循环中(这在原始问题中没有出现),我打印出了每个对象的序列(这是一个数组)。它显示所有对象的@78308db1。这是否意味着它是相同的参考?我太糊涂了
public Key(String name, Note[] notes) {
    this.sequence = Note.NOTES.clone();
    ...
}