2011-02-08 18 views
6

プログラムからジェネリックタイプを使用すると、アプリケーションのパフォーマンスが低下することがあります。私はコレクションオブジェクト(リスト、セット、マップ)をたくさん使い、アプリケーションに柔軟性を持たせるために(このアプリケーションは他のアプリケーションに統合する必要があります)、パラメータ化する代わりにジェネリック型のみを使用しました。これは一般的な慣習ですか、それとも誰かが提案/助言を持っていますか?パフォーマンスの著しい低下はありますか?事前に一般的なタイプとパフォーマンス

おかげで、

+0

「パラメータ化するのではなく、ジェネリック型」とまったく同じ意味ですか?生のタイプを使用している(つまり、一般的なタイプの情報を指定していない)ということを意味していると思います。 –

+0

私はあなたができるところで、特定の/パラメータ化された型を使用することをお勧めします。 –

+1

パフォーマンスが異なる場合でも、キャストなどで古くて非一般的な方法を行った場合、開発時間とバグの点でどのくらいのコストがかかりますか?これも重要で、ジェネリックのような言語機能では、実際のパフォーマンスの考慮事項よりも重要です。パフォーマンスが考慮されていれば、それはジェネリックに関するすべての説明とチュートリアルの全体に塗りつぶされます。 – fwielstra

答えて

11

ジェネリック医薬品は効果的に「コンパイル時のトリック」であるため、すべてのでもパフォーマンスの低下はありません。

コンパイラは、この情報を使用して、ランタイム時にジェネリックを使用しない場合に表示される特定の安全でないプラクティスを拒否します。実行時には、生のクラス(ジェネリックパラメータの上限)のみが使用されるため、ジェネリックスを使用してではなくと同じパフォーマンスが得られ、クラスを自分でキャストします。

+1

それは少し遅くコンパイルするかもしれません;) –

1

ジェネリックの使用は、パフォーマンスやメモリ消費に大きな影響を与えません。

一般的なタイプの情報は、一般的に実行時には利用できないということが最も簡単です。つまり、ジェネリック型の情報がある場合と全く同じように、JVMはまったく同じように動作します。

「柔軟性を持たせる」という生の型だけを使用することは、コレクションに型情報を持たないため、コードを扱う準備ができていなくても、あらゆる種類のオブジェクトを渡すことができるためです。 (すなわち、あなたのコードがStringオブジェクトのコレクションを期待していて、Integerのコレクションを渡すと、ClassCastExceptionがスローされます。(正しく実装された)ジェネリックでは、コンパイル時エラーです。

2

ジェネリック型は、型の安全性を(任意の型キャストの問題は、ランタイムないコンパイル時の間に表示されます)prividingされており、さらに「消去」であり、コンパイラへの命令は基本的に(消去を)とに表示されません。そのフォーム(実行時に明示的キャストに置き換えられます)。したがって、パフォーマンス上のペナルティはありません。

0

ジェネリックの定義はすべてデザインタイムのみです。プログラムをコンパイルすると、JVMはすべての定義をキャストで置き換えます。これは、最初から必要な正しいタイプを含むようにクラスをコーディングしてキャストを回避するのと比べて、パフォーマンスがわずかに低下します。

パフォーマンスの低下は小さく、コードの可読性と再利用性を高めるために、適切な場合はジェネリックを使用することを強くお勧めします。これらの暗黙的なキャストを行うメソッドが非常に多く使用されているクラスがあり、パフォーマンスの問題が発生している場合は、もちろんこれを考慮する必要があります。しかし、前にはない;-)。

2

多くの場合、ジェネリックを使用してもパフォーマンスに影響はありません。パフォーマンスの唯一の問題は、プリミティブ型をオブジェクト型で置き換える必要がある場合です(たとえば、intを汎用パラメータとして渡す必要がある場合など)。

ただし、オブジェクトを集中的に使用する場合を除き、パフォーマンスペナルティは表示されません。したがって、ジェネリックで始める必要があります。この特殊なケースに起因するパフォーマンスの問題が発生した場合でも、プリミティブタイプを使用するクラスでジェネリックオブジェクトを置き換えることができます。

+0

ニコラスのフレーズ "初期の最適化は悪い"のおかげで。私はこれを諦めてそこから抜け出す必要があると思う。方法を書いた後、私はすぐにその性能について心配し始め、可能な限り「最適化」を誘発しようとします。 – Ozyman

+0

「初期最適化」と診断できます。リファクタリング、それをより明確にして、それを実行してください。遅いと思われる場合は、アルゴリズムレベルで考えてください。それがうまくいかない場合は、トリックを使用して限界問題を「ジェネリックの原型」として最適化します。 – Nicolas

+0

これは全く意味がありません。ジェネリックスのもとでオブジェクトを使用する必要がある場合は、ジェネリックスの前に同じ場所でオブジェクトを使用する必要があります。例えば'ArrayList 'を今使っていれば、ジェネリックが存在する前に 'ArrayList'に' Integer'オブジェクトを入れなければなりません。 'int'を使うには、ジェネリックの有無にかかわらず、別のクラスが必要です。 – newacct

0

通常、それはすべてコンパイル時の魔法です。場合によっては、隠された実行時コストが存在することがあります。

class A<T> 
1  void f(T arg) 

    class B extends A<String> 
2  void f(String arg) 

    A<String> a = new B(); 
3 a.f("blah"); 

3行目では、メソッド2が呼び出されます。しかし、最初にメソッド1を呼び出しますが、メソッド2は従来の「オーバーライド」メソッド1ではなく、シグネチャが異なります。 Javacは2つを橋渡ししなければならず、実行時にメソッド1からメソッド2までのコストが発生します。

JVMメソッドのインライン化によってコストを最適化することはできません。