保存せずに新しいオブジェクトを作成するのは悪い習慣ですか?


23

オブジェクトへの参照を保存せずにJavaコードで作成されたオブジェクトを見てきました。たとえば、Eclipseプラグインで、次のように作成されたSWTシェルを見ました。

new Shell();

この新しいShellオブジェクトは変数に格納されませんが、ウィンドウが破棄されるまで参照されたままになります。ウィンドウが閉じられると、デフォルトで[信じる?]が発生します。

参照を保存せずにこのようなオブジェクトを作成するのは悪い習慣ですか?または、ライブラリの設計が不十分でしたか?参照の必要はないが、オブジェクトの「副作用」のみが必要な場合はどうなりますか?とにかく参照を保存する必要がありますか?

更新:

確かに、私の上記の例は貧弱です。このように作成されたUI要素を見てきましたが、Shellインスタンスでopenメソッドを呼び出す必要があるため、このようなSWTシェルの作成はおそらく無意味です。Java並行性チュートリアルの次のような、aix提供するより良い例があります。

(new HelloThread()).start();

このプラクティスは多くのコンテキストで見られるため、疑問が残ります。それは良い習慣ですか?


2
参照を保存するポイントは何ですか?
ダニエルRヒックス

(おそらく、概念的な観点から、Shell.createTopLevelShell()このような場合にコンストラクターを使用するよりも、静的メソッドを使用する方が良いでしょう。しかし、機能的にはほとんど違いはありません。)
Daniel R Hicks

この質問は、オブジェクトを参照せずにオブジェクトを作成する方法、この方法を必要とするクラスを作成する方法、またはSWTがこの種のパターンを使用する方法に関するものですか?
StriplingWarrior

1
SWTオブジェクトはdispose()dでなければなりません: ルール1:作成した場合は、破棄します。 eclipse.org/articles/swt-design-2/swt-design-2.html
jbindel

2
デバッグの目的で参照を保持するために変数を使用します。このメソッドにブレークポイントがある場合、デバッガーにローカル変数を介してオブジェクトを照会させることができます。参照なしでは可能だと確信していますが、おそらくもっと難しいでしょう。
マーティンヨーク

回答:


12

これには個人的な好みの要素がありますが、参照を保存しないことは必ずしも悪い習慣ではないと思います。

次の仮想的な例を考えてみましょう。

new SingleFileProcessor().process(file);

すべてのファイルに対して新しいプロセッサオブジェクトを作成する必要process()があり、呼び出し後に必要ない場合、そのオブジェクトへの参照を保存しても意味がありません。

Java 同時実行性チュートリアルから取った別の例を次に示します。

(new HelloThread()).start();

参照が保存されていないときに、他の多くの例を見てきました。

String str = new StringBuilder().append(x).append(y).append(z).toString();

StringBuilderオブジェクトは保持されません。)

common.lang'sなどを含む同様のパターンがありますHashCodeBuilder


2
@BalusC:敬意を表して、何が魚っぽいのか、ファクトリーメソッドがどのように優れているのかわかりません(あなたの例は私のものに似てgetInstance()おり、シングルトンではなくファクトリーだと思います)。
NPE

シングルトンを使用するかどうかは、工場次第です。工場の呼び出し元はそれについてあまり考えるべきではありません。
ドナルドフェローズ

あなたの例では、FileProcessorインスタンスは(おそらく)文が完了したら不要です。一方、OPの例では、Shellインスタンスは(カバーの下で)別のオブジェクトによって参照され、その参照(したがってShellオブジェクト)はステートメントの期間。
ダニエルRヒックス

@BalusC:FileProcessorには、の動作を変更する追加のメソッドがありprocessます。
ケビンクライン


5

一般に、参照を合理的にリリースできる限り迅速にリリースすることをお勧めします。次の間に違いはありません。

HelloThread thread = new HelloThread();
thread.start();
// where thread is never used for the rest of the method

そして

(new HelloThread()).start();

コードに関する限り、変数名の使用を避けているだけであり、これは肯定的なことかもしれません。JITコンパイラーは一般に、最後に使用した後にスレッドをガベージコレクションできることを認識できるほど賢いので、おそらくパフォーマンスの観点から違いはありません。

回避すべき唯一の本当の問題は、Constructor Anti-Patternのコードですが、それがあなたが求めているもののようには聞こえません。


3

SWTを使用している場合、これは悪い場合があります。自分でクリーンアップする必要があるためです(dispose()メソッドを呼び出します)。しかし、他のクラス(非SWT)では問題ありません。

オペレーティングシステムリソースの管理に関する記事を次に示します。


循環参照は、オブジェクトがJavaでガベージコレクションされるのを防ぎません。最新のJava VMは、オブジェクトが到達可能かどうかに基づいてオブジェクトがGC可能かどうかを判断し、参照カウントを使用しません。
jbindel

2
実際、参照カウントは使用しません。しかし、SWTはdispose()を呼び出す必要がある特殊なケースですが、最初にretain()を呼び出す必要はありません。
アレックス

非SWTのケースのみを参照するつもりでした。
jbindel

ここではオペレーティング・システム・リソースの管理についての記事だeclipse.org/articles/swt-design-2/swt-design-2.htmlは
アレックス

2
その場合、誤解を招く可能性があるため、回答を編集して「GCに不可能」に関する記述を削除してください。
ドナルドフェローズ

1

まず第一に、Javaの前にCまたはC ++を学んだ人を困らせることになります。読者がそれが長所か短所かを判断するための演習として、それを残しておきます。

オブジェクトが非常に短命になるように設計されている状況は確かにありますが、ほとんどの場合、オブジェクトを作成するのに十分な複雑さがある場合、参照を保持する十分な理由があるほど複雑なので、少なくとも何かを見逃したかどうかを再確認するように警告してください。

たとえば、チュートリアルでは誰もスレッド参照を保持することを気にしませんが、実際には、スレッドを生成するのに時間がかかる場合、通常はスレッドをキャンセルできるようになるのに十分な時間がかかります。または、寿命が短い場合は、通常、join続行する前に必要な多数のスレッドを生成します。または、スレッドの作成が実際に成功したことを確認する必要があります。または、終了する前にスレッドが完全に終了することを確認する必要があります。写真が撮れます。


2
他の言語のプログラマーの迷惑を心配することは本当に最初の懸念ですか?
ボタン840

多くの人が引き継ぐスタイルであるため、チームの構成によっては読みやすさ、親しみやすさ、スタイルの問題になります。C ++でプログラミングしたことがない人でさえ、指導したメンターのスタイルを採用することがよくあります。
カールビーレフェルト
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.