ラッパークラスとプリミティブ型を使用する場合


回答:


69

他の人はCollections、オブジェクトを必要とするような特定の構造や、オブジェクトはそれらの基本的な対応物(メモリとボクシング)よりもオーバーヘッドが多いと述べています。

別の考慮事項は次のとおりです。

オブジェクトを初期化しnullたりnull、メソッドやコンストラクターにパラメーターを送信して、状態や機能を示すと便利です。これはプリミティブでは実行できません。

多くのプログラマーは、これを示すために数値を0(デフォルト)または-1に初期化しますが、シナリオによっては、これが正しくないか、誤解を招く可能性があります。

これはまたNullPointerException、何かが誤って使用されているときにシーンを設定します。これは、将来の任意のバグよりもはるかにプログラマーフレンドリーです。


15
「オブジェクトをnullに初期化すると便利です。」これは正しくないため便利ではありません。フィールドがオプションの場合は、明示的に指定する必要があります。
Eddie Jamsession、2015年

8
笑@EddieJamsessionありがとう、私は二度とnullに初期化しません。(pfffft)
2015

@EddieJamsession実際の値の設定が失敗したときに失敗を示す方法としてオブジェクトをnullに初期化する場合、この問題をキャッチするために他にどのように提案しますか?ああ、これを入力しているときに気づきました。例外。NullPointerExceptionは一般的すぎます。非常に具体的なカスタム例外を使用して、問題の原因を示した方がよいでしょう。いいですね、これからやっていきます...
klaar

1
@EddieJamsession問題について読んだ後、オプションオブジェクトのコンセプトに出会いました。正しい。
klaar 2017年

18

一般に、なんらかの理由(たとえば、コレクションに入れるなど)でオブジェクトが必要でない限り、プリミティブ型を使用する必要があります。それでも、数値パフォーマンスを最大化したい場合は、オブジェクトを必要としない別のアプローチを検討してください。これはドキュメントで推奨されおり、この記事では、オートボクシングがパフォーマンスに大きな違いをもたらす方法を示しています。


3
パフォーマンスへの影響はそれほど大きくないため、コードの読みやすさ/信頼性は後退します。
スタントン2009年

2
まず、プリミティブを適切に使用しても、コードが読みにくくなることはありません。次に、パフォーマンスへの影響が大きい場合があります。決してそうではないと言うのは馬鹿げている。
Matthew Flaschen、2009年

1
@pstanton:Integerより読みやすい方法を説明してくださいint
スティーブンC

多くの場合、Integerはintほど読みやすくはありません。これらの場合は常にintを使用します。特定の変数がnullにならないことがわかっている場合は、intを使用します。ただし、オブジェクトが準備されていないことを示すためにnullに初期化できるため、多くの場合、オブジェクトが使用されるとき、別のプログラマーが変数の状態を理解するのは簡単です。たとえば、一意の増分する数値IDを持つ未保存のデータベースレコードがある場合、有効なIDを割り当てる前に、このIDを0、-1、またはnullにする必要がありますか?その場合、オブジェクトの方が優れています。
スタントン2009年

パフォーマンスに関して-特別なケースでは、パフォーマンスへの影響が大きくなる可能性があります。つまり、これらのオブジェクトを非常に迅速に多数作成している場合や、一定期間に多くのオブジェクトを構築している場合です。しかし、私はまともなプログラマーがこれらの特殊なケースを特定し、それに応じて回避または修正できることを期待しています。それが決して重要ではないと言ったことはありませんが、一般的に言えば、重要ではありません。
スタントン、

12

私の意見では、クラスメンバーがラッパー変数である場合、デフォルト値に依存しません。これは、開発者が使いやすい動作です。

1。

class Person {
   int SSN ; // gets initialized to zero by default 
}

2。

class PersonBetter {
  Integer SSN; //gets initialized to null by default
}

最初のケースでは、SSN値を初期化しないでおくことはできません。使用する前に値が設定されているかどうかを確認しないと、問題が発生する可能性があります。

2番目のケースでは、SSNをnullで初期化しておくことができます。これはNullPointerExceptionを引き起こす可能性がありますが、SSNフィールドを初期化せずに使用しようとするたびに、無意識のうちにデフォルト値(ゼロ)をSSNとしてデータベースに挿入するよりも優れています。


3
ビルダーパターンはこれを回避するためのものです。このシナリオでPersonBuilderは、Personインスタンスを取得するために「ビルド」を呼び出す前にSSNが設定されていない場合に例外をスローするを作成します。この種のことは過剰だと思いますが、それはJava言語が適切なパターンを促進するためのものです。
Sandy Chapman

8

必要な場合にのみ、ラッパータイプを使用します。

それらを使用することで、彼らがそうであるという事実を除いて、あなたは多くを得ませんObjects

また、メモリ使用量のオーバーヘッドと、ボックス化/ボックス化解除に費やされた時間を失うことになります。


4
多くは得られないかもしれませんが、多くは失うことはありません。1990年代のパームパイロットで実行している場合を除きます。
スタントン2009年

それらがオブジェクトであることは、単純なプリミティブとしてよりもはるかに多くのコンテキストとカプセル化を提供します。そのため、これらのプリミティブが何を意味するのか、およびそれらがどこで使用されているのかに応じて、実際に多くを得ることができます。
aberrant80

4

実際には、ラッパークラスの使用を説明できる状況に遭遇しました。

longタイプ変数を持つサービスクラスを作成しました

  1. 変数がタイプであるlong場合-初期化されていない場合、0に設定されます-GUIに表示されるとユーザーを混乱させます
  2. 変数がタイプのLong場合-初期化されていない場合、次の値に設定されますnull-このnull値はGUIに表示されません。

これは、Booleanプリミティブを使用すると値がより混乱する可能性がある場合にも適用さbooleanれます(デフォルト値がfalseであるため)。


3

コレクションは、単純なJavaラッパーオブジェクトの典型的な例です。ただし、コード(値オブジェクト)でWrapperに特定の意味を与えることを検討する場合があります。

私見ほとんどの場合、コードの可読性と保守性に要約すると、値オブジェクトを使用する利点があります。オブジェクトに特定の責任がある場合、オブジェクト内で単純なデータ構造をラップすると、コードが単純化されることがよくあります。これは、ドメイン駆動設計で非常に重要なことです。

もちろんパフォーマンスの問題もありますが、適切なデータを使用してパフォーマンスを測定し、問題のある領域に向けたより具体的なアクションを実行できるようになるまで、それを無視する傾向があります。コードも理解しやすいと、パフォーマンスの問題も理解しやすくなります。


3

パフォーマンス数値計算が支配的なアプリケーションのは、プリミティブを使用することで大きなメリットが得られます。

プリミティブ型、は==演算子を使用しますが、ラッパーの場合、equals()メソッドを呼び出すことをお勧めします。

「有害と見なされるプリミティブタイプ」、「手続き型の意味論を他の点では均一なオブジェクト指向モデルに混合するため」。

多くのプログラマーは、これを示すために数値を0(デフォルト)または-1に初期化しますが、シナリオによっては、これが正しくないか、誤解を招く可能性があります。


1

コレクションを使用する場合、Wrapperクラスを使用する必要あります。

プリミティブ型は、配列に使用されます。また、カウンターやブール条件など、動作のないデータを表すため。

オートボクシング以降、「プリミティブまたはラッパーをいつ使用するか」というフロンティアはかなりあいまいになりました。

ただし、ラッパーはオブジェクトであるため、Javaの優れた機能をすべて利用できることを忘れないでください。たとえば、リフレクションを使用してIntegerオブジェクトを作成できますが、int値は作成できません。ラッパークラスには、valueOfなどのメソッドもあります。


コレクション以外に、ラッパークラスを使用しないでください。Integer i = new Integer(10);のような通常の宣言に使用するのはどうでしょうか。このようにしてもいいですか?
Gopi

オートボクシングでは、整数i = 10を実行できます。
トム

1
いいえ、スリ。私がオブジェクトであるという要件がない場合は、オブジェクトにしないでください。
Matthew Flaschen、2009年

オートボクシングは、上で宣言したiをint i = 10またはInteger i = 10にアンボックスしますか?
Gopi

3
int pi = new Integer(10); 動作します。整数oi = 10; 動作します。int ni = null; 動作しません。LHSは、RHSが必要とするものに変換されます。
スタントン2009年

0

値タイプを作成する場合。ProductSKUやAirportCodeなど。

プリミティブ型(私の例では文字列)が同等性を定義している場合、同等性をオーバーライドする必要があります。


5
文字列はプリミティブではありません
pstanton

2
文字列を含む値型を基本オブジェクトとしてラップすることには、まだ十分な理由があります。
Chris Missal

あなたの答えは意味がありません。あなたの言っていることがよくわかりません。私はあなたのコメントに同意しますが、ラッパークラスは読みやすさを向上させるのであれば良い考えです。
スタントン2009年

値タイプまたは値オブジェクトは作成され、不変である必要があります。たとえば、「CountryCode」オブジェクトを次のように作成しても意味がありません:new CountryCode( "USA")次に、同じ方法で別のオブジェクトを作成します。最初は文字列ですが、その背後には意味があります。文字列を使用することで、それらを変更できます(データを追加するなどして)が、それらは同じではなくなります。私が説明しようとしていることのより良い説明についてはこの記事を参照してください:)これが理にかなっている
Chris Missal

0

Javaのプリミティブ値はオブジェクトではありません。これらの値をオブジェクトとして操作するために、java.langパッケージは、各プリミティブデータ型のラッパークラスを提供します。

すべてのラッパークラスが最終です。開始できるすべてのラッパークラスのオブジェクトは不変です。つまり、ラッパーオブジェクトの値は変更できません。

ただし、voidクラスはラッパークラスと見なされますが、プリミティブ値をラップせず、開始できません。パブリックコンストラクターはなく、キーワードvoidを表すクラスオブジェクトを表すだけです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.