Javaでは、すべての変数(ローカルまたはクラス)を宣言し、それらが実際の場合はfinalパラメータを宣言する習慣があります。
これにより、コードがより詳細になりますが、これにより、コードの読み取り/把握が容易になり、意図が明確に示されるため、間違いを防ぐことができます。
これについてあなたはどう思いますか、そしてあなたは何をしますか?
Javaでは、すべての変数(ローカルまたはクラス)を宣言し、それらが実際の場合はfinalパラメータを宣言する習慣があります。
これにより、コードがより詳細になりますが、これにより、コードの読み取り/把握が容易になり、意図が明確に示されるため、間違いを防ぐことができます。
これについてあなたはどう思いますか、そしてあなたは何をしますか?
回答:
それはすべて、優れたコーディングスタイルに関係していると思います。もちろん、final
どこでも多くの修飾子を使用しなくても、優れた堅牢なプログラムを書くことができますが、考えてみると...
変更しfinal
てはならないすべてのものに追加すると、あなた(または次のプログラマー、コードに取り組んでいる人)がコードの原因となった思考プロセスを誤って解釈または誤用する可能性を狭めるだけです。少なくとも、以前は不変だったものを変更したいときに、いくつかのベルが鳴るはずです。
最初は、それは一種のたくさん見ることが厄介なルックスのfinal
あなたのコード内のキーワードを、しかしかなりすぐには言葉自体に気付いて停止されますと、単純に考えるだろう、その-事-意志-決して変更-から-この-ポイント-上に(あなたは私からそれを取ることができます;-)
いい練習だと思います。私はいつもそれを使っているわけではありませんが、できて、何かfinal
にラベルを付けるのが理にかなっているときは、それをやります。
final
は、コンパイラーは間違いを犯した場合、続行を許可しません。
final
保存するたびに、可能な限り変更しない変数を追加するオプションがあります。
final
です。それは98%の時間で違いを生じさせません、それは時間の%1のマイナーな不便ですが、1%の時間は私が愚かまたは意図されていないことをすることから私を救う価値があります。
final
コードを「クリーンアップ...」するときはいつでもEclipseに修飾子を随所に追加させます。「どこでも」とは、catch()ブロック内であっても意味し、前述のように、しばらくするとそれらに気付かないでしょう。もちろん、言語を作成する場合final
、がデフォルトで、var
またはmodifiable
がオプションのキーワードになります。
にこだわる:
検討するが慎重に使用する:
肛門を感じない限り無視してください:
finalキーワードを使用する前に、完全な使用法を理解する必要があります。変数、フィールド、メソッド、クラスに適用でき、異なる影響を及ぼします
詳細については、以下にリンクされている記事をチェックすることをお勧めします。
final
特に変数の修飾子は、コンパイラーに、一般的に賢明な規則を適用させる手段です。つまり、(ローカルまたはインスタンス)変数が正確に1回だけ割り当てられるようにします(それ以上)。変数が使用される前に確実に割り当てられるようにすることで、NullPointerException
次の一般的なケースを回避できます。
final FileInputStream in;
if(test)
in = new FileInputStream("foo.txt");
else
System.out.println("test failed");
in.read(); // Compiler error because variable 'in' might be unassigned
変数が2回以上割り当てられるのを防ぐことにより、広範囲にわたるスコープを抑制することができます。これの代わりに:
String msg = null;
for(int i = 0; i < 10; i++) {
msg = "We are at position " + i;
System.out.println(msg);
}
msg = null;
これを使用することをお勧めします:
for(int i = 0; i < 10; i++) {
final String msg = "We are at position " + i;
System.out.println(msg);
}
いくつかのリンク:
私は可能なすべての変数を宣言することについてかなり独断的ですfinal
。これには、メソッドパラメータ、ローカル変数、まれに値オブジェクトフィールドが含まれます。最終的な変数をどこでも宣言する主な理由は3つあります。
ただし、最終的なクラスとメソッドは、最終的な変数参照ほど有用ではないと思います。final
これらの宣言で使用されるキーワードは、単に自動テストとあなたが予想したことがない可能性があることな方法であなたのコードの使用に障害物を提供しています。
final
変数とメソッドパラメータは、バイトコードで表現されないため、パフォーマンスに影響を与えません。
効果的なJavaには、「不変オブジェクトを優先する」という項目があります。フィールドをfinalとして宣言すると、これに向けて小さな一歩を踏み出すのに役立ちますが、もちろんそれ以外にも、真に不変のオブジェクトにははるかに多くのものがあります。
オブジェクトが不変であることがわかっている場合は、同期の心配なしに多くのスレッド/クライアント間でオブジェクトを共有して読み取ることができ、プログラムの実行方法を推論するのは簡単です。
変数に最後のキーワードを設定することで間違いを犯したことがないので、今のところ、それは大きな時間の無駄だと思います。
実行する本当の理由がない限り(その変数が最終的なものであると特定の点を説明したい場合など)、コードの可読性が低下することがわかったので、実行しないでください。
ただし、コードが読みづらくなったり、長く書けなくなったりする場合は、どうぞそれを試してください。
編集:明確にするために(そして、反対票を取り戻すための試みとして)、定数を最終としてマークしないでください、私は次のようなことをしないと言っています:
public String doSomething() {
final String first = someReallyComplicatedExpressionToGetTheString();
final String second = anotherReallyComplicatedExpressionToGetAnother();
return first+second;
}
(私の意見では)コードを読みにくくするだけです。
また、最後に行うことはすべて、変数を再割り当てできないようにすることであり、変数を不変にしたり、そのようなものにしたりすることはありません。
final
最後のキーワードを使用することに対する最大の議論のように聞こえるのは、「それは不必要」であり、「スペースを浪費する」ということです。
ここの多くの素晴らしい投稿で指摘されているように、「ファイナル」の多くの利点を認め、タイピングとスペースが増えることを認めながら、Javaはデフォルトで変数を「ファイナル」にして、「コーダーがそれを望んでいる場合、「可変」。
final
「コードが長すぎる」、「コードが不格好になる」以外の議論はありません。にはいくつかの引数がありますfinal
。また、手動で入力したくない場合は、保存時に自動的に追加できます。
私はfinal
常にオブジェクト属性に使用しています。
final
オブジェクトの属性に使用された場合のキーワードは、視認性の意味を持っています。基本的に、最終オブジェクト属性の値の設定は、コンストラクターが戻る前に行われます。これは、this
参照をコンストラクターからエスケープせずfinal
、すべての属性に使用する限り、オブジェクトは(Java 5セマンティクスの下で)正しく構築されることが保証されており、不変であるため、安全に公開できることを意味します他のスレッドへ。
不変オブジェクトは、スレッドセーフだけではありません。また、変更可能なスペースは意図的に変更され、一貫して使用された場合、変更する必要のあるものだけに完全に制限されるため、プログラムの状態遷移を簡単に推論できます。
また、メソッドをfinalにすることもありますが、それほど頻繁ではありません。私はめったにクラスをファイナルにしません。私はほとんど必要がないので、私は一般的にこれを行います。私は通常、継承をあまり使用しません。代わりにインターフェイスとオブジェクト構成を使用することを好みます。これは、テストしやすい設計に適しています。具象クラスの代わりにインターフェースにコーディングする場合、jMockなどのフレームワークを使用すると、テスト時に継承を使用する必要がありません。具象クラスを使用するよりも、インターフェースを使用してモックオブジェクトを作成する方がはるかに簡単です。
クラスの大部分をファイナルにする必要があると思いますが、まだハビにはいっていません。
仕事のためにたくさんのコードを読まなければなりません。インスタンス変数のfinalが欠落していることは、私を困らせる一番の原因の1つであり、コードの理解を不必要に難しくしています。私のお金では、ローカル変数のfinalは明快さよりも混乱を引き起こしています。言語はそれをデフォルトにするように設計されている必要がありますが、私たちは間違いに耐えなければなりません。特にループやif-elseツリーでの明確な割り当ての場合に役立つことがありますが、ほとんどの場合、メソッドが複雑すぎることを示します。
finalは明らかに定数に使用し、不変性を強制する必要がありますが、メソッドには別の重要な使用方法があります。
効果的なJavaには、これに関する全体の項目(項目15)があり、意図しない継承の落とし穴を指摘しています。継承のためにクラスを設計および文書化していない場合、効果的には、クラスから継承すると予期しない問題が発生する可能性があります(アイテムは良い例です)。したがって、継承を意図していないクラスやメソッドでfinalを使用することをお勧めします。
それは厳しいと思われるかもしれませんが、それは理にかなっています。他の人が使用するためにクラスライブラリを作成している場合は、そのために設計されていないものから継承したくない-後方互換性のために、クラスの特定の実装にロックされます。チームでコーディングしている場合、チームの別のメンバーが本当に必要な場合にファイナルを削除するのを止めることはできません。しかし、キーワードは彼らに彼らが何をしているのかを考えさせ、継承元のクラスがそのために設計されたものではないことを警告しますので、彼らは特に注意する必要があります。
Javaで変数を使用すると、FinalはC ++の定数の代わりになります。したがって、finalおよびstaticが変数に使用されると、不変になります。同時に、移行されたC ++プログラマーをかなり満足させます;-)
参照変数と共に使用すると、オブジェクトを操作することはできますが、オブジェクトを再参照することはできません。
メソッドでfinalを使用すると、サブクラスによってメソッドをオーバーライドできなくなります。
使用法が非常に明確になったら、注意して使用する必要があります。メソッドでfinalを使用してもポリモーフィズムは役に立たないため、これは主に設計に依存します。
変数の値が決して変更されない、または変更されるべきでないと確信している場合にのみ、変数に使用してください。また、SUN.forの推奨するコーディング規則に従っていることを確認してください。例:final int COLOR_RED = 1; (アンダースコアで区切られた大文字)
参照変数では、特定のオブジェクトへの不変の参照が必要な場合にのみ使用します。
読みやすさの部分については、final修飾子を使用するときにコメントが非常に重要な役割を果たすようにします。
私はローカル変数でそれらを使用することはありません。追加された冗長性にはほとんど意味がありません。変数を再割り当てする必要がないと考えている場合でも、次の人が別の方法でコードを変更することにはほとんど違いがありません。また、コードが変更されているため、最終的なものにするという元々の目的が無効になる場合があります。明確にするためだけの場合は、冗長性の悪影響のために失敗すると思います。
定数の場合を除いて、ほとんどメリットがないので、メンバー変数にもほとんど同じことが当てはまります。
また、不変であることの最良の指標は、そのように文書化されていること、および/またはオブジェクトを変更できるメソッドがないことです(これは、クラスをfinalにすることと一緒に、不変です)。
しかし、ちょっと、それは私の意見です:-)
議論については、私はそれらは必要ではないと思います。モストリーは、単に読みやすさを損なうだけです。引数変数の再割り当てはめちゃくちゃ愚かなので、とにかく定数として扱うことができると確信しています。
Eclipseが最終的に赤く色付けされるという事実は、コード内の変数宣言を見つけやすくするため、ほとんどの場合、readbillityが改善されると思います。
私は、すべての変数がfinalでなければならないというルールを適用しようとします。そうでなければ、極端な正当な理由はありません。「この変数は何ですか?」と答える方がはるかに簡単です。初期化を見つけ、それがそれであると確信しなければならない場合は、質問してください。
私は実際に、今日、ファイナルではない変数についてかなり緊張しています。それは、ナイフが糸にぶら下がっているのか、それとも単にキッチンの引き出しがあるのかの違いのようです...
最後の変数は、ラベル可能な値へのちょうど良い方法です。
最終でない変数は、バグが発生しやすいアルゴリズムの一部にバインドされています。
優れた機能の1つは、ほとんどの場合、アルゴリズムの問題として変数を使用するオプションが、代わりにメソッドを記述することであり、通常はコードが大幅に改善されることです。
私はしばらくコーディングしていて、できる限りfinalを使用しています。これを(変数、メソッドパラメータ、およびクラス属性に対して)しばらく実行した後、私の変数の90%(またはそれ以上)が実際には最終であると言えます。変更したくないときに変数を変更しないことの利点(以前に見たことがありますが、それはときどき苦痛です)は、コード内の追加の入力と追加の "最終"キーワードの犠牲になります。
そうは言っても、言語を設計する場合、他のキーワードで変更しない限り、すべての変数をfinalにします。
クラスやメソッドにはfinalをあまり使わないと思いました。クラスがユーティリティクラスでない場合(この場合、プライベートコンストラクターは1つだけにする必要があります)、これは多かれ少なかれ複雑な設計の選択です。
また、Collections.unmodifiable ...を使用して、必要に応じて変更不可能なリストを作成します。
イベントリスナーなどに匿名ローカルクラスを使用することは、Javaの一般的なパターンです。finalキーワードの最も一般的な使用法は、スコープ内の変数に偶数リスナーがアクセスできるようにすることです。
ただし、コードに多くの最終ステートメントを配置する必要がある場合。それはあなたが何か間違ったことをしている良いヒントかもしれません。
上記の記事はこの例を示しています。
public void doSomething(int i, int j) {
final int n = i + j; // must be declared final
Comparator comp = new Comparator() {
public int compare(Object left, Object right) {
return n; // return copy of a local variable
}
};
}
クラスをfinalとマークすると、実行時ではなくコンパイル時にいくつかのメソッドバインディングが発生する可能性もあります。以下の "v2.foo()"を検討してください。コンパイラはBがサブクラスを持つことができないことを知っているため、foo()をオーバーライドできないため、呼び出す実装はコンパイル時にわかります。クラスBがfinalとマークされていない場合、v2の実際のタイプは、Bを拡張してfoo()をオーバーライドするクラスである可能性があります。
class A {
void foo() {
//do something
}
}
final class B extends A {
void foo() {
}
}
class Test {
public void t(A v1, B v2) {
v1.foo();
v2.foo();
}
}