5

私は Java プログラマーではありません。「final」に関するドキュメントを読み、「変数の値は一度しか設定できない」という意味だと理解しました。

一部の Java を C# に翻訳しています。コードが期待どおりに実行されません。理由を理解しようとしたところ、意味をなさない final の使用法がいくつか見つかりました。

コード スニペット 1:

final int[] PRED = { 0, 0, 0 };
...
PRED[1] = 3;

PRED[1] は 0 か 3 か?

コード スニペット 2:

final int[] PRED = new int[this.Nf];
for (int nComponent = 0; nComponent < this.Nf; nComponent++) {
    PRED[nComponent] = 0;
}
...
PRED[1] = 3;

PRED[0] は 0 のままでしょうか?

4

6 に答える 6

6

finalJava の配列に適用されるキーワードのセマンティックを誤解していると思います。

どちらの Java の例でも、配列は変更されませんが、要素は変更される可能性があります。すべての割り当てが正しく実行され、配列に格納されている値が変更されます。ただし、試してみると

final int[] PRED = new int[this.Nf];
// some other code
PRED = new int[123]; // <<== Compile error

コンパイルエラーが表示されます。

コードを C# に変換する場合、 as ( に適用される場合) または as (メンバーに適用される場合) のfinalいずれかに変換する必要がある場合があります。C# の配列と Javaの配列の意味は同じです。プログラムで配列を再割り当てすることはできませんが、その要素を自由に変更できます。sealedclassreadonlyreadonlyfinal

最後に、Java 固有のケース whenfinalが C# ではまったく必要ない場合に使用されます。Java で匿名ローカル クラスのメソッド内で変数を使用する必要がある場合、その variable を作成する必要がありますfinal。C# には匿名ローカル クラスがないため、そのコードを別のもの (おそらく匿名デリゲート) に変換する必要があります。このようなデリゲートは、読み取り専用変数の使用に制限されていません。

于 2012-05-02T10:40:14.693 に答える
3

C# で探している単語は "const" です。

const int SOMETHING = 10;

SIZE も定数でなければならないことに注意してください。

また、定数は int、bool、string、char などの型のみにすることができます (基本型のみ)。

したがって、配列やクラスなど、何か他のものが必要な場合は、次のようにできます。

static readonly int[] PRED = new int[this.Nf];

静的な読み取り専用は、論理的に正確に const を意味しますが、舞台裏で少し異なるように定義されているため、より自由に操作できます。(できる場合 - 静的な読み取り専用の代わりに定数を定義する必要があります)

配列自体は実行中に変更されないため、これを行うことはできません。

PRED = new int[3]; // Error
PRED = null; // Error
PRED = PRED; // Error

ただし、PRED 配列内の値を変更することはできます。

PRED[0] = 123;

読み取り専用のコレクションが必要な場合は、ReadOnlyCollection オブジェクトを使用できます。そのオブジェクトも定数にしたい場合は、静的読み取り専用の組み合わせを使用できます (定数はクラスであるため使用できません)。次のようになります。

static readonly ReadOnlyCollection<int> PRED = new ReadOnlyCollection<int>(new[] {1, 2, 5, 6});

そして、PRED は常に PRED であり、サイズは常に 4 であり、常に 1、2、5、6 を含みます。

PRED = PRED; // Error (static readonly)
PRED = null; // Error (static readonly)
PRED[1] = 0; // Error (ReadOnlyCollection enforces readonly on the elements)

int i = PRED[1]; // Still works, since you aren't changing the collection.
于 2012-05-02T10:39:07.507 に答える
2

final は、実行時ではなく、コンパイラによってチェックされます。そのため、割り当てPRED[1] = 3が無効な場合、コンパイラによってキャッチされ、コードはコンパイルされません。

この割り当ては有効です。これは、最終的な手段として、別の値を変数に再割り当てできないためです。変数によって参照されるオブジェクトを変更できないという意味ではありません。

上記の代入は の値を変更しませんPRED。の値を変更しますPRED[1]。PRED がリストの場合、同等のものは になりますPRED.set(1, 3)。どちらでも構いません。間違っているのは ですPRED = new ArrayList<Integer>()

于 2012-05-02T10:42:02.010 に答える
1

すでに述べたように、final変数は一度しか設定できません。しかし、その値を変更することは合法です。

于 2012-05-02T10:41:17.297 に答える
1

Java final キーワードは、さまざまな条件下で Java プログラミング言語で使用され、さまざまな意味を持ちます。例えば:

  1. 定数変数を宣言するには、
  2. 定数メソッド パラメーターを宣言します。

    1. final として宣言された変数は、使用する前に初期化する必要があります。この変数には、(a = b) などの新しい値を割り当てることはできません。ただし、変数がプリミティブ型でない場合は、set メソッドまたはその他のパブリック フィールドを使用してそのプロパティを設定できます。つまり、オブジェクト インスタンス参照は変更できませんが、オブジェクト インスタンスのプロパティは、それ自体が final と宣言されていない限り変更できます。

    2. パラメータが使用されているメソッドで変更されることを禁止します。

于 2012-05-02T11:03:06.323 に答える
1

値を一度だけ設定したい場合は、java の final の代わりに、c# または const で readonly を使用するか、場合によっては seal を使用する必要がありますが、読み取りのみが必要な場合は readonly の方が良いでしょう ;)

于 2012-05-02T10:38:58.020 に答える