我整天都在研究这个问题,但我找不到解决办法。我理解使用子类的问题以及编译器如何不知道该类实际上是什么,因为在调用add之前可以将其设置为其他类。我到处看,我仍然不知道如何解决这个问题。我有一个抽象类,它是一个文件包装器。文件包装器有一个sheetwrappers的arraylist。我希望具体的excelfile类能够将excelsheets添加到它的arraylist中,但我一直收到这个错误:
类型ArrayList中的方法add(capture#2-of?extends SheetWrapper)不适用于参数(ExcelSheet)
这是必要的代码。此处仅粘贴错误中涉及的部分.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 :(得分:1)
好吧,您将变量声明为扩展ArrayList
的某些元素的“SheetWrapper
”。这意味着您无法向其添加ExcelSheet
的实例,因为它实际上可能是ArrayList
扩展SheetWrapper
的其他类型的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;
不是协变的。
如果您的所有代码实际上都在同一个地方,那么只需在分配之前填写您的列表:
excelSheets
如果您需要从代码的不同部分执行此操作,只需将本地提升为另一个私有或受保护字段(例如sheets
)和继承的{{1}},然后使用它。
答案 1 :(得分:0)
请参阅GenericsFAQ。你只想:
protected List<SheetWrapper> sheets;
请注意,使用接口类型“List”比变量声明的具体实现类“ArrayList”更好(除非该类需要特定的方法)。
答案 2 :(得分:0)
第二种可能性是使FileWrapper本身通用:
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的列表。