Javaに定数機能がないのはなぜですか?


140

Javaで定数の背後にある理由を特定しようとしていましたが、Javaではfinalキーワードを使用して定数を宣言できることがわかりました。

私の質問は、Javaが定数(const)機能を導入しなかった理由です。多くの人がC ++から来たと言っているので、C ++にはconstキーワードがあります。

あなたの考えを共有してください。


2
キーワードありますconst基本的な機能はありません。タイトルとタグを適宜修正しました。
ローンの侯爵

回答:


142

重いC ++コーディングからJavaに移行するたびに、Javaのconst-correctnessの欠如に適応するのに少し時間がかかります。constC ++ でのこの使用法は、知らない場合に定数変数を宣言することとは大きく異なります。基本的には、const-pointerと呼ばれる特別な種類のポインターを介してアクセスしたときにオブジェクトが不変であることを保証します。副作用があってはならないメソッドのみを含む。残念ながら、これは言語によって強制されていません。

ウィキペディアでは、このテーマに関する次の情報を提供しています。

興味深いことに、Java言語仕様では、constを予約済みキーワード(つまり、変数識別子として使用できないキーワード)と見なしていますが、セマンティクスは割り当てられていません。キーワードの予約は、Java言語の拡張にC ++スタイルのconstメソッドとconst型へのポインターを含めることができるようにするために行われたと考えられています。Javaでconstの正確性を実装するためのJava Community Processの拡張リクエストチケットは2005年に閉鎖されました。これは、constの正確性がおそらく公式のJava仕様に反映されないことを意味します。


10
finalただし、Java も同様です。
reinierpost 2014年

62
いいえ、そうではありません。finalたとえば、C ++ constメソッドとは完全に異なる動作をするメソッド。
dom0 2014年

7
@reinierpost プロパティまたは変数finalキーワード、プロパティまたは変数が一度だけ割り当てられることを保証するだけです。たとえば、副作用を持つメソッドを呼び出すことによって、このオブジェクトの状態を変更することもできます。finalポインタではなくオブジェクトを参照するという点でC ++のスタック割り当てにいくぶん似ていますが、それだけです。これはもちろんdom0がすでに言ったことに加えてです。
Tim

9
finalJavaではconst、値型の場合はC ++のように機能しますが、T&参照型の場合はC ++非定数のように機能します
Mark K Cowan

1
最後は統合失調症のキーワードです。再割り当てを防ぐ一方で、変数をクロージャーに公開するためにも使用されます。私は再割り当てを防ぎたいがそれらの変数を公開したくないかもしれませんが、それを行う方法はありません。私の意見では、これはかなりよく考えられていない言語機能です。
David Bradley

82

どういうconst意味か
まず、「const」キーワードのセマンティクスは、人によって意味が異なることを理解してください。

  • 読み取り専用参照 -Java finalセマンティクス-参照変数自体を別のインスタンス(メモリロケーション)を指すように再割り当てすることはできませんが、インスタンス自体は変更可能です
  • 読み取り専用の参照 -C constポインター/参照セマンティクス-この参照はインスタンスの変更に使用できないことを意味します(例:インスタンス変数に割り当てられない、変更可能なメソッドを呼び出せない)-参照変数のみに影響するため、非const参照が同じインスタンスがインスタンスを変更する可能性があります
  • 不変オブジェクト -インスタンス自体は変更できないことを意味します-インスタンスに適用されるため、非const参照は許可されないか、インスタンスの変更に使用できません
  • 上記のいくつかの組み合わせ
  • その他

なぜか、なぜそうでないconst
か、本当に「賛成派」と「反対派」の議論の一部を掘り下げたい場合は、この拡張要求(RFE)の「バグ」の下の説明を参照してください。このRFEは、「読み取り専用参照」タイプの「const」機能を要求します。1999年にオープンし、2005年にSunによってクローズ/却下された「const」トピックは、激しく議論されました。

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4211070

双方には多くの良い議論がありますが、しばしば引用される(しかし、必ずしも説得力のある、または明確なわけではない)理由にconstは、次のものがあります。

  • 誤用および/または悪用される可能混乱の意味を有することができる(参照const平均以上の)
  • 他の方法で利用可能な機能を複製する場合があります(例:不変クラスを設計する、不変インターフェースを使用する)
  • 機能クリープである可能性があり、値によるオブジェクトの受け渡しのサポートなど、その他のセマンティックの変更が必要になる

これらが良い理由か悪い理由かについて誰かが私に議論する前に、これらは私の理由でないことに注意してください。これらは、私がRFEの議論をざっと読んで得たいくつかの理由の「要点」にすぎません。私は必ずしも自分自身に同意するわけではありません。単に、私ではなく一部の人々がconstキーワードが良い考えではないかもしれないと感じる理由を挙げようとしています。個人的には、より明確な方法で言語に導入される「const」セマンティクスがもっと欲しいです。


2
回答の2番目の部分だけを+1します。多くのキーワードには重要な意味があります。volatile理解するのはとても簡単ですか?またはfinal?ええ。
einpoklum 2015年

OTOH、Javaは、これらの重要な機能をできるだけ使用しないように設計されています。そして、彼らがその目標を達成したと言っているのではありません(またはJavaがその目標から逸脱していません)。しかし、その理由でそれを除外することには、まだメリットがあったかもしれません。他に複雑なことがあるのは、それ以上紹介しない理由です(または、D言語になってしまいます)。
Maarten Bodewes

7

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_cast、を使用せずにconst / non-constエイリアスを取得するため、constが変更されないことを意味すると考える習慣がますます危険になります。const単に、コードがキャストなしではコードを変更できないことを意味し、値が定数であることを意味しません。


3
const int x = 42; -xは定数

2
@Neil constポインタと非constポインタの両方によってエイリアスされた1つのオブジェクトまたは変数がある場合、constエイリアスの値はnon-constエイリアスによって変更できます。したがってconst、値が一定であることを意味しません。これは、値のクライアントがそれを変更しないように制約されていることを意味します。あなたの例ではエイリアスがないので、すべてのユーザーが同じ制約を受けています。これは一般的なケースではありません。const値ではなくクライアントに影響します-変更できない、変更されないというわけではありません。
ピートカーカム

1
const-correctnessは、プログラマーできることではなく、プログラマーがすべきこと に関するものです。皆さんもその点を理解しているようです。ただ、因果読者が興味を持つ可能性がセントのカップルを追加したい:のようなデザインパターンをimmutable interfaceし、immutable objectJavaで模倣のconstへの(キャストと反射とbeatable)別の方法があります。"真の" constは、SealedObjectを使用して実行できますが、オブジェクトのユースケースが破壊されます。
Martin Andersson、

6
プログラムの結果は定義されていないことに注意してください。const_castはconst変数を変更するためのものではありません。const変数をAPIに渡すためのもので、constが正しくないものの、値を変更しません。何かconstが変更されないと考える習慣は良いものだと思います。なぜなら、変更された場合、プログラムには、使用するコンパイラーによってはいつでも壊れる可能性があるハックが含まれているからです。
Cygon 2015

1
定数から生まれた値を変更することは、未定義の動作です。ディスクはすでにフォーマットされている可能性があります。
浙江省

5

これは少し古い質問ですが、このスレッドが今日の会話で出てきたので、とにかく2セントを寄付すると思いました。

これはなぜconstがないのか正確に答えていませんか?しかし、クラスを不変にする方法。(残念ながら、受け入れられた回答へのコメントとして投稿するにはまだ十分な評判がありません)

オブジェクトの不変性を保証する方法は、クラスを不注意に設計することです。これは、変更可能なクラスよりも少し注意が必要です。

これは、Josh Blochの効果的なJava アイテム15-最小化の可変性に戻ります。本をまだ読んでいない場合は、コピーを手に取り、数回読んでください。比喩的な"Javaゲーム"が表示されることを保証します。

項目15でBlochは、オブジェクトの状態を保証するためにクラスの可変性を制限する必要があることを示唆しています。

本を直接引用するには:

不変クラスは、インスタンスを変更できないクラスです。各インスタンスに含まれるすべての情報は、作成時に提供され、オブジェクトの存続期間中は修正されます。Javaプラットフォームライブラリには、String、ボックス化されたプリミティブクラス、BigIntegerおよびBigDecimalなど、多くの不変クラスが含まれています。これには多くの理由があります。不変クラスは、可変クラスよりも設計、実装、使用が簡単です。エラーが発生しにくく、より安全です。

次に、Blochは、5つの単純なルールに従って、クラスを不変にする方法を説明します。

  1. オブジェクトの状態を変更するメソッド(セッター、ミューテーターなど)を提供しない
  2. クラスを拡張できないことを確認してください(つまり、クラス自体をとして宣言しますfinal)。
  3. すべてのフィールドを作成しますfinal
  4. すべてのフィールドを作成しますprivate
  5. 変更可能なコンポーネントへの排他的アクセスを保証します。(オブジェクトの防御コピーを作成することにより)

詳細については、本のコピーを入手することを強くお勧めします。


3
C ++のconstは、フルスケールの不変性よりもはるかに柔軟です。ある意味で、「const」は「この特定のコンテキスト内では不変」と見なすことができます。例:不変ではないクラスがありますが、特定のパブリックAPIを介して変更されないようにする必要があります。Gunslinger47によって提案されているようにインターフェイスを作成(およびそのパブリックAPIに返す)すると、Javaでも同じことが実現しますが、それは醜いです(したがって、ほとんどのJava開発者はこれを無視して、不要な混乱を引き起こしています)。 。
無バグノウサギ

3

のC ++セマンティクスはconst、Java とは大きく異なりますfinal。デザイナーが使用しconstていたとしたら、それは不必要に混乱していたでしょう。

const予約語であるという事実は、設計者がを実装するためのアイデアを持っていることを示唆していますがconst、それ以来、彼らはそれを拒否しました。このクローズされたバグを参照してください。上記の理由には、C ++スタイルのサポートを追加constすると互換性の問題が発生することが含まれます。


-1

Javaで「const」変数を作成する方法がありますが、これは特定のクラスに対してのみです。finalプロパティを持つクラスを定義し、それをサブクラス化するだけです。次に、「const」を使用する基本クラスを使用します。同様に、「const」メソッドを使用する必要がある場合は、それらを基本クラスに追加します。コンパイラーは、基本クラスの最終メソッドであると考えるものを変更することを許可しませんが、サブクラスのメソッドを読み取って呼び出します。


この例をいくつか教えていただけますか?
NO_NAME 2017年

クラスMYStringはGetString {private final String aaaa;を実装します。public String getString(); }クラスMutableStringはGetString {private String aaaa2;を実装します。public String getString(); public String setString()}
user1122069

-2

定数を定義するには2つの方法があります- conststatic final、まったく同じセマンティクス。さらにstatic final、より良い動作を説明しますconst


@Bozho、あなたはConstよりも良い振る舞いを言った、それはどのようにですか?例を教えてください
gmhk 2010

変数はstatic(特定のインスタンスに属していない)であり、final変更できません。
Bozho 2010

-2

static finalを使用して、Constと同様に機能するものを作成できます。これは過去に使用しました。

protected static final int cOTHER = 0;
protected static final int cRPM = 1;
protected static final int cSPEED = 2;
protected static final int cTPS = 3;
protected int DataItemEnum = 0;

public static final int INVALID_PIN = -1;
public static final int LED_PIN = 0;

これは効果のない戦略だという噂を聞いたので、噂ベースの最適化に反対票を投じました。
afarley

答えからうわさを取り除いた。静的なfinal intを使用して、constスタイルのコードを作成できます。
ハミッシュ

承知しました。反対票を削除しました。多分他の反対票のいくつかはswitchステートメントに関するものです(それがあなたの例の残りの部分とどう関係しているのですか?)
afarley

switchステートメントでは、cRPMをconstであるかのように使用しました。上記を考慮すると、かなり正しいです。はい、スイッチを取り外しました。
ハミッシュ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.