2009-07-22 16 views
0

私はこの一日中研究しており、解決策を見つけることができません。私は、サブクラスの使用の問題と、コンパイラが実際にどのようなものかを知ることは理解しています。なぜなら、addを呼び出す前にそれを別のものに設定する可能性があるからです。私はどこにでも見えますが、この問題を解決する方法はまだ分かりません。私はファイルラッパーである抽象クラスを持っています。ファイルラッパーはsheetwrappersのarraylistを持っています。私は具体的なクラスの優秀なクラスが、そのarraylistにエクセルシートを追加できるようにしたいが、このエラーが発生し続ける:一般的なクラスの問題!

ArrayListタイプのadd(キャプチャ#2??extends SheetWrapper)は引数には適用されない(Excelシート)

ここに必要なコードです。エラーに関連する部分のみがここに貼り付けられます.ExcelSheetも抽象クラスです。どんな助けも非常に高く評価されます。ありがとう!

public abstract class FileWrapper { 

    protected ArrayList<? extends SheetWrapper> sheets; 


public class ExcelFile extends FileWrapper { 

    this.sheets = new ArrayList<ExcelSheet>(); 
    for(int i = 0; i < wb.getNumberOfSheets(); i++) 
    { 
     if(ParserTools.isLegitSheet(wb.getSheetAt(i))) 
     { 
      this.sheets.add(new ExcelSheet(null)); //ERROR HERE 
     } 
    } 
+0

'ExcelSheet'は実際には' SheetWrapper'を拡張していますか? – Joey

+0

はい!だから申し訳ありませんが、私はそれを言い忘れました。 – Danny

答えて

1

さて、あなたは「SheetWrapperを拡張するいくつかの要素のArrayList」として変数を宣言しました。これは、実際にArrayListSheetWrapperを拡張する)のタイプになる可能性があるため、ExcelSheetのインスタンスを追加できないことを意味します。

より正確には、add()は共変型ではありません。

すべてのコードが同じ場所に実際にある場合は、それを割り当てる前に、あなたのリストを埋める:

ArrayList<ExcelSheet> sheets = new ArrayList<ExcelSheet>(); 
for(int i = 0; i < wb.getNumberOfSheets(); i++) 
{ 
    if(ParserTools.isLegitSheet(wb.getSheetAt(i))) 
    { 
      sheets.add(new ExcelSheet(null)); //ERROR HERE 
    } 
} 
this.sheets = sheets; 

あなたは、コードの異なる部分からそれを実行する必要がある場合は、ちょうどにそれがローカル持ち上げます継承されたsheetsの横に別のプライベートフィールドまたは保護フィールド(例:excelSheets)を置き、それを使用してください。

+0

恐ろしい!迅速な対応に感謝します。一つの小さな質問です。たぶん私はコンパイラの動作について少し混乱していますが、シートをExcelシートのArrayListに初期化した場合、コンパイラはこれがexcesheetsのarraylistであることを知っていないので、Excelシートを追加できます。それは奇妙に聞こえるが、コンパイラがなぜ私がarraylistを始めたら、それはエクセルシートだけを保持するということを自明に知っているのだろうか?もう一度おねがいします – Danny

+0

'if..else'ステートメントがあれば、その1つの枝に' new ArrayList 'で変数を初期化し、もう1つは別のものですか?一般に、コンパイラは宣言されている_variable_の型のみを考慮します(したがって、Javaが静的に型付けされている理由)。追加の型情報をその変数の使用方法から除外しようとはしません。 –

+0

アチャア!今や意味をなさない本当にありがとう! – Danny

0

GenericsFAQを参照してください。あなたは、単にたい:(特定のメソッドは、そのクラスから必要とされない限り)インターフェイスタイプ「リスト」を使用すると、変数宣言のための具体的な実装クラス「のArrayList」に好適であることを

protected List<SheetWrapper> sheets; 

注意を。

public abstract class FileWrapper<T extends SheetWrapper> { 

    protected ArrayList<T> sheets; 


    public class ExcelFile extends FileWrapper<ExcelSheet> { 

     this.sheets = new ArrayList<ExcelSheet>(); 
     for(int i = 0; i < wb.getNumberOfSheets(); i++) 
     { 
      if(ParserTools.isLegitSheet(wb.getSheetAt(i))) 
      { 
        this.sheets.add(new ExcelSheet(null)); 
      } 
     } 
    } 
} 

こうすることで、あなたはどこにでもExcelFileでExcelSheetのリストとしてのシートを使用することができます。

+1

私は、派生クラスに(Listの特定のインスタンス化で初期化することによって)含まれる特定のタイプの要素を制限させたいと思うと思います。さもなければ、私はなぜ彼が最初にワイルドカードを望むのか分からない。 –

+0

特定のインスタンス化で初期化すると、リストに含めることができる値が制限されます。ジェネリックはコンパイル時のみです。あなたが言っていることが真実なら、彼が望むのはCollections.checkedListです。 –

+0

私は彼が 'public abstract class FileWrapper {protected final List sheets;}を望んでいると思っています。とにかく「保護された」悪いです。 –

0

第2の可能性は、のFileWrapper自体は一般的なようにすることです。