0

最初にこのスニペットを見てください:

public MultiThreadManager( Class<T> c) {
    T[] allJobs = (T[]) Array.newInstance( c , MAX_THREAD_SIZE ) ;
    for ( int i = 0 ; i < MAX_THREAD_SIZE ; i ++ ) {
        allJobs[i] = (T) new Object();
        service.submit( allJobs[i] );
        getWaitingThreads().add( allJobs[i] );
    }           
}

例外は次のとおりです。

Exception in thread "main" java.lang.ClassCastException: java.lang.Object cannot be cast to slave.JobTemplate

私がやろうとしていること:

MultiThreadManager のコンストラクターは、Callable を実装するジェネリック型 ( Job.java など) を取る必要があります。これらすべての汎用データ型 ( Job,java ) の配列を作成します。汎用データ型 ( Job.java ) のコンストラクターが実行され、エグゼキューター サービスで実行されるように初期化します。

私のエラーを特定するのを手伝ってください。または、より良い方法を提案してください。

前もって感謝します

ありがとうございました。しかし、物事はもう少し複雑です: Herez その他の情報:

public class Job extends JobTemplate<String> {...details ...}
public abstract class JobTemplate< T > implements Callable<T> {...details..}

そして最後に

MultiThreadManager< Job > threadManager = new MultiThreadManager< Job >( Job.class );

もう一度ありがとう:)

4

3 に答える 3

5

配列を作成する必要があるのと同じように、さらにリフレクションが必要になります。

allJobs[i] = c.newInstance();

これらの厄介なチェック例外をすべて try-catch で囲みます。

ただし、new Callable[]実際のジョブ タイプの詳細に入る必要がないため、使用することをお勧めします。リフレクションが不要な設計も考慮する必要があります。呼び出し元は、クラス オブジェクトを渡す代わりに、ジョブをインスタンス化します。現在のソリューションは、デフォルトのコンストラクターを介してのみインスタンス化される Job タイプの制限に悩まされています。

于 2013-11-16T20:30:37.153 に答える
3

と言うとnew Object()、クラス Object の新しいオブジェクトが作成されます。その動的な実行時の型は Object です。したがって、実際に が でTない限り、へのキャストは論理的に有効ではありません。TObject

を作成するために必要なことは、Tリフレクションを使用して で適切なコンストラクターを呼び出すことTです。

于 2013-11-16T20:24:45.627 に答える
2

Robin と Marko が問題の原因を示しました。Joshua Bloch による「Effective Java」から、もう 1 つ強調しておきたいことがあります。

項目 25: 配列よりもリストを優先する
... 配列とジェネリックでは、型規則が大きく異なります。配列は共変で具体化されています。ジェネリックは不変で消去されます。結果として、配列は実行時の型安全性を提供しますが、コンパイル時の型安全性を提供しません。ジェネリックの場合はその逆です。一般的に言えば、配列とジェネリックはうまく混在しません。それらを混ぜてコンパイル時のエラーや警告が表示される場合は、最初に配列をリストに置き換える必要があります。

説明:

共変- たとえば、オブジェクトの配列が整数の配列のスーパータイプであることを意味します。List<Integeer>ジェネリックは不変です。つまり、 aを a にキャストすることはできませんList<Object>

具体化- コンパイル時に配列に存在するすべての情報は、実行時にも利用できます。ジェネリックは消去によって実装されます。つまり、型制約はコンパイル時にのみ適用され、その後消去されます (実行時には存在しません)。

要約すると、
配列とジェネリックを混在させると、問題が発生する可能性が高くなります。配列の代わりにリストを使用して、2 つを混在させないようにしてください。

public <T> void MultiThreadManager(Class<T> c) 
                throws IllegalAccessException, InstantiationException {

    List<T> allJobs = new ArrayList<T>(MAX_THREAD_SIZE) ;
    for (int i = 0; i < MAX_THREAD_SIZE; i++) {
        allJobs.add(c.newInstance());
        service.submit( allJobs.get(i) );
        getWaitingThreads().add( allJobs.get(i));
    }
}
于 2013-11-16T20:38:49.187 に答える