45

チュートリアルによると:

修飾子は、修飾子staticと組み合わせて、final定数を定義するためにも使用されます。修飾子は、このfinalフィールドの値を変更できないことを示します。

関係するタイプが原始的である場合にのみ、これに同意します。参照型、たとえば、Point2D位置属性がないfinal(つまり、位置を変更できる)クラスのインスタンスでは、この種の変数の属性はpublic static final Point2D A = new Point2D(x,y);変更できます。これは本当ですか?

4

15 に答える 15

67

はい、変更できます。参照のみを変更できますが、その内部フィールドは変更できます。次のコードはそれを示しています:

public class Final {
    static final Point p = new Point();
    public static void main(String[] args) {
        p = new Point(); // Fails
        p.b = 10; // OK
        p.a = 20; // Fails
    }
}

class Point {
    static final int a = 10;
    static int b = 20;
}

Groovy(代替JVM言語)には@Immutableと呼ばれるアノテーションがあり、オブジェクトが構築された後、オブジェクトの内部状態への変更をブロックします。

于 2013-01-16T12:42:54.850 に答える
16

正解です。変更することはできます。この場合の「静的ファイナル」は、参照自体を指し、変更することはできません。ただし、参照しているオブジェクトが変更可能である場合は、参照しているオブジェクトを変更できます。

文字列などの不変オブジェクトは定数になります。

于 2013-01-16T12:41:34.170 に答える
10
public static final Point2D A = new Point2D(x,y);

ここでは、参照 A最終的なものであり、クラス内のではありませんPoint2D

静的ファイナルを定義した後は、これを行うことはできません。

//somewhere else in code
A = new Point2D(x1,y1);
于 2013-01-16T12:41:41.813 に答える
6

public static final Point2D A = new Point2D(x、y); まだ変更される可能性があります。これは本当ですか?

Aの参照は変更できませんでしたが、属性がfinalでない場合は、関連する真のオブジェクトの値を変更できます。

class Point2D{
  private int x;
  private int y;
  <getter & setter>
} 
class Constant{
  Public static final Point2D A = new Point2D(1,2);
  public static void main(String[] args){
     A.setX(10); // this will work 
     A = new Point2D(10,20);// this will not work
  }
}

Point2D's属性がfinalの場合、Point2D classはになりますimmutable

または、クローン可能なオブジェクトを送信できます。

好き -

 private static final Point2D A = new Point2D(x,y);
 public static getA(){
     return A.clone();
 }
于 2013-01-16T12:41:30.750 に答える
6

それは本当です。修飾子は、final可能な限り推移的ではありません。

これは、参照が変更されないことを意味するだけです。参照の内容(オブジェクトのフィールド)は、時間の経過とともに変化する可能性があります。

于 2013-01-16T12:41:51.110 に答える
2

ポイントへの参照(Aあなたの場合)は変更できません。オブジェクトの状態のみを変更できます。Point2Dしたがって、新しいものを作成して変数に割り当てることはできません。

于 2013-01-16T12:41:18.867 に答える
2

参照のみが最終的なものであり、参照されるオブジェクトは変更できます(整数などの不変オブジェクトでない限り)。そうです、それは「定数」の与えられた値に対してのみ一定です。

于 2013-01-16T12:42:23.073 に答える
1

はい。

もちろん、他の場所で説明されているように、後で最終フィールドの値を変更することもできます

于 2013-01-16T18:50:39.247 に答える
1

あなたはここで非常によく似た質問を見つけることができます:非常に良い説明があります:

ここで: なぜ最終オブジェクトを変更できるのですか?

ちなみに私は反射メカニズムについて考え始めました…。

理論的には...所有しているクラスインスタンスを取得できると信じています。次に、クラスメンバーを取得し、現在のインスタンスを見つけて、それが最終的なものであることを確認します...。

私はそれをチェックしませんでした、そしてそれが可能であるかどうかさえ知りません-それはただの考えです(多分?)

public class Final {
    static final Point p = new Point();

    public static void main(String[] args) throws MyImmutableException {
        p = new Point(); // Fails
        p.setB(10); // OK
        p.setA(20); // Fails - throws MyImmutableException
    }
}       

public class Point() {
    int a = 10;
    int b = 20;

    public setA(int a) {
        this.a = a;
    }
    public setB(int b) throws MyImmutableException {
        detectIsFinal()
        this.b = b;
    }

    private void detectIsFinal() throws MyImmutableException {
        int mod = this.getClass().getModifiers()
        if (Modifier.isFinal(mod)) {
            throw new MyImmutableException();
        }
    }   
}

public class MyImmutableException extends Exception { 
    public MyImmutableException() {super(); }
}

私はあなたが他に何ができるかを考えていました...再びそれはただの!!!!!!!!!です 擬似コード!!! それがうまくいくかどうかはわかりません:P

おそらく、注釈の知識を持っている人が刺激を受けて、それを機能させるでしょう。残念ながら、今週はこれ以上時間がありません。後で、POCを作成しようとします。

public class Final {
    @Immutable
    static final Point p = new Point();

    public static void main(String[] args)  {
        p = new Point(); // Fails
        p.setB(10); // Fails
        p.setA(20); // OK
    }
}       

public class Point() {
    int a = 10;
    @ImmutableOnThisInstance
    int b = 20;

    @DetectIsImmutable
    public setA(int a) {            
        this.a = a;
    }

    @DetectIsImmutable
    public setB(int b) {
        this.b = b;
    }      
}


class Immutable {
    ?????????????????
}

class DetectIsImmutable {
    /**
     * Just a pseudocode - I don't know how to work with ANNOTATIONS :) :) :)
     * SORRY :)
     * @throws MyImmutableException
     */
    private void detectMethod() throws MyImmutableException {
        Immutable instance = CLASS_THAT_IS_ANNOTATED.getClass().getAnnotation(Immutable.class)
        if (instance != null) {
            // get parent Method invocation name (from stacktrace list)
            String methodName = .............;
            if (methodName.startsWith("set")) {
                // check id we have variable with this settername
                String fieldName = ...; // cut "set" get rest of it, make first letterSmall 
                // find this field in object fields
                Field f = this.getClass().getDeclaredField(fieldName);
                if (f.getAnnotation(ImmutableOnThisInstance.class) != null) {
                    throw MyImmutableException();
                }
            }
        }
    }           

}
于 2013-01-22T19:35:06.010 に答える
0

それはまだ真実です。

あなたが引用する主張が真実である方法があります。は変数static finalを記述し、その変数は変更できないことは事実であり、定数も同様です。変数はオブジェクトへのポインタであり、そのオブジェクトは変更できます。しかし、それは変数が定数であることを止めません。

これは、C ++で実現できるほど強力ではない真実の方法ですが、それはconst何かです。

于 2013-01-16T12:42:30.303 に答える
0

はい。それで合っています。参照は変更できませんが、参照されるオブジェクトは変更できます。このようなものは完全に合法です:

public static final List<Object> someList = new ArrayList<Object>();

// ...

someList.add(someThing); // <-- this would be illegal if the referenced object was also constant
于 2013-01-16T12:42:32.027 に答える
0

Point2Dのプロパティを変更することはできますが、その新しいインスタンスを作成することはできません。

また、Point2Dは抽象であるため、これを拡張する子クラスのインスタンスを作成する必要があります。

于 2013-01-16T12:43:08.797 に答える
0

他のすでに述べたように、静的なfinalであるのはPoint2Dオブジェクトへの参照であり、属性xおよびyではありません。Point2Dオブジェクトの位置を変更できないようにする場合は、Point2Dクラスで属性xおよびyを静的および最終(初期化)に設定する必要があります。

于 2013-01-16T14:09:59.520 に答える
0
static final Point2D A = new Point2D(x,y);

それが言うのは、クラスの参照はPoint2D変更できないということだけです。

            _____________
           |             |
A----------|--->(x,Y)    |
           |             | 
           |_____________|Heap

したがって、別のオブジェクトをポイントしてAを変更することはできませんが、もちろん、(x、y)の値またはポイントオブジェクトのコンテンツを変更することはできます。

オブジェクトも一定にしたい場合は、Pointオブジェクトを不変にする必要があります。

于 2013-01-29T06:09:00.267 に答える
0

参照変数がfinalとして宣言されている場合、オブジェクトを参照していると、その変数に新しいオブジェクトを再割り当てすることはできません。ただし、最終参照変数が指しているオブジェクトの状態を変更することはできます。以下の例を見てください。

class A
{
    int i = 10;
}

public class UseOfFinalKeyword
{
    public static void main(String[] args)
    {
        final A a = new A();  //final reference variable

        a.i = 50;
        //you can change the state of an object to which final reference variable is pointing

        a = new A();  //compile time error

        //you can't re-assign a new object to final reference variable
    }
}

詳細については、リンクをたどってください:Javaのfinalキーワード

于 2015-03-21T14:04:15.750 に答える