Java の定数の背後にある理由を特定しようとしていましたが、Java ではfinal
キーワードを使用して定数を宣言できることを知りました。
const
私の質問は、Java が定数 ( ) 機能を導入しなかった理由です。多くの人が C++ から来たと言うので、C++ にはconst
キーワードがあります。
あなたの考えを共有してください。
負荷の高い C++ コーディングから Java に移行するたびに、Java のconst-correctnessの欠如に適応するのに少し時間がかかります。このconst
C++ での の使用法は、定数変数を宣言することとは大きく異なります。基本的に、const-pointer と呼ばれる特別な種類のポインターを介してアクセスしたときに、オブジェクトが不変であることを保証します Java では、通常は const-pointer を返したい場所で、代わりにインターフェイス型の参照を返します副作用があってはならないメソッドのみが含まれています。残念ながら、これは言語によって強制されていません。
ウィキペディアでは、この件に関する次の情報が提供されています。
興味深いことに、Java 言語仕様は const を予約済みのキーワード (つまり、変数識別子として使用できないもの) と見なしていますが、セマンティクスを割り当てていません。キーワードの予約は、Java 言語の拡張機能に C++ スタイルの const メソッドと const 型へのポインターを含めることができるようにするために発生したと考えられています。Java で const の正確性を実装するための Java コミュニティ プロセスの拡張要求チケットは 2005 年に終了しました。
どういうconst
意味
か
まず、「const」キーワードのセマンティクスが人によって意味が異なることを理解してください。
final
セマンティクス - 参照変数自体を別のインスタンス (メモリの場所) を指すように再割り当てすることはできませんが、インスタンス自体は変更可能ですconst
ポインター/参照セマンティクス - この参照を使用してインスタンスを変更できないことを意味します (たとえば、インスタンス変数に代入できない、変更可能なメソッドを呼び出すことはできません) - 参照変数のみに影響するため、非 const 参照は同じインスタンスがインスタンスを変更する可能性があります2番目に、「賛成」対「反対」の議論のいくつかを本当に掘り下げたい場合は、この拡張要求 ( RFEconst
) の「バグ」の下の議論を参照してください。この RFE は、「読み取り専用参照」タイプの「const」機能を要求します。1999 年に公開され、2005 年に Sun によって閉鎖/拒否された「const」トピックは、活発に議論されました。
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4211070
どちらの側にも多くの良い議論がありますが、よく引用される (ただし、必ずしも説得力のある、または明確ではない) 反対の理由には次のconst
ものがあります。
const
てください) 。これらが良い理由か悪い理由かについて誰かが私に議論しようとする前に、これらは私の理由ではないことに注意してください. それらは、私が RFE の議論をざっと読んで集めた理由のいくつかの「要点」にすぎません。私自身、必ずしもそれらに同意するわけではありません。私は単に、一部の人々 (私ではない) がconst
キーワードを適切でないと感じる理由を挙げようとしているだけです。個人的には、明確な方法でより多くの「const」セマンティクスが言語に導入されることを望んでいます。
const
C++ では、値が定数であることを意味しません。
const
C++ では、コントラクトのクライアントがその値を変更しないことを約束することを意味します。
スレッドベースの並行性をサポートする環境にいる場合、式の値がconst
変化するかどうかはより明白になります。
Java は最初からスレッドとロックの同時実行をサポートするように設計されているため、用語をオーバーロードしてセマンティクスを持たせることで混乱を招くことはありませんでしたfinal
。
例えば:
#include <iostream>
int main ()
{
volatile const int x = 42;
std::cout << x << std::endl;
*const_cast<int*>(&x) = 7;
std::cout << x << std::endl;
return 0;
}
42 を出力し、次に 7 を出力します。
x
としてマークされていconst
ますが、非 const エイリアスが作成さx
れるため、定数ではありません。すべてのコンパイラがこの動作を必要とするわけではありませんvolatile
(ただし、すべてのコンパイラが定数のインライン展開を許可されています)。
より複雑なシステムでは、を使用せずに const/non-const エイリアスをconst_cast
取得するため、 const は何かが変更されないことを意味すると考える習慣を身につけると、ますます危険になります。const
コードがキャストなしでは変更できないことを意味するだけであり、値が定数であるということではありません。
これは少し古い質問ですが、今日このスレッドが話題になったので、とにかく 2 セントを寄付しようと思いました。
これは、なぜconstがないのか正確には答えていませんか? ただし、クラスを不変にする方法。(残念ながら、受け入れられた回答へのコメントとして投稿するには、まだ十分な評判がありません)
オブジェクトの不変性を保証する方法は、不変になるようにクラスをより慎重に設計することです。これには、可変クラスよりも注意が必要です。
これは Josh Bloch のEffective Java Item 15 - Minimize Mutabilityに戻ります。この本をまだ読んでいない場合は、コピーを手に取り、数回読んでください。この本があなたの比喩的な「Java ゲーム」を刺激することを保証します。
項目 15 で Bloch は、クラスの可変性を制限して、オブジェクトの状態を保証する必要があることを提案しています。
本を直接引用するには:
不変クラスは、単にインスタンスを変更できないクラスです。各インスタンスに含まれるすべての情報は、インスタンスの作成時に提供され、オブジェクトの存続期間中固定されます。Java プラットフォーム ライブラリには、String、ボックス化されたプリミティブ クラス、BigInteger および BigDecimal など、多くの不変クラスが含まれています。これには多くの正当な理由があります: 不変クラスは、可変クラスよりも設計、実装、および使用が容易です。エラーが発生しにくく、より安全です。
次に Bloch は、次の 5 つの簡単な規則に従って、クラスを不変にする方法を説明します。
final
)。final
。private
。詳細については、本を入手することを強くお勧めします。
の C++ セマンティクスはconst
Java とは大きく異なりますfinal
。設計者が使用const
していた場合、不必要に混乱していたでしょう。
が予約語であるという事実const
は、設計者が を実装するためのアイデアを持っていたことを示唆していますが、その後、実装const
しないことに決めました。このクローズドバグを参照してください。記載されている理由には、C++ スタイルのサポートを追加するconst
と互換性の問題が発生することが含まれます。
Java で「const」変数を作成する方法はありますが、特定のクラスに対してのみです。最終的なプロパティを持つクラスを定義し、それをサブクラス化するだけです。次に、「const」を使用する基本クラスを使用します。同様に、「const」メソッドを使用する必要がある場合は、それらを基本クラスに追加します。コンパイラは、基本クラスの最終メソッドと見なされるものを変更することを許可しませんが、サブクラスのメソッドを読み取って呼び出します。
定数を定義するには、まったく同じセマンティクスを持つ と の 2 つの方法がありconst
ますstatic final
。さらにstatic final
、よりも優れた動作を説明しますconst