我在堆栈溢出中搜索了此错误,但是没有一个设计和我一样。对于术语的建议,以帮助找到类似下面的示例代码的类似主题,将不胜感激。
这是一个演示该错误的简单测试用例:
import java.util.List;
public class SimpleTest {
abstract class AbsTask<T>
{
}
abstract class AbsQueue<T extends AbsTask<?>>
{
private List<T> lst;
public void addSpecialItem()
{
lst.add(new SpecialItem()); // Error occurs here
}
}
class SpecialItem extends AbsTask<Void>
{
}
}
我想添加到我的抽象类的方法AbsQueue称为addSpecialItem,这将插入SpecialItem类到列表中的通用列表T中基本上是列表AbsTask。
这是错误: The method add(T) in the type List is not applicable for the arguments (SimpleTest.SpecialItem)
如果我输入case如下所示,我可以解决此错误:
lst.add((T)new SpecialItem());
是否有处理这种不类型转换的方式new SpecialItem()来T?
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
在Java中,泛型是为了提供类型安全和编译时检查而设计的。当你声明一个泛型类如AbsQueue<T>
时,你期望T是一个特定的类型或者满足某种约束(例如继承自某个类或实现某个接口)。在你的例子中,你希望T是AbsTask
或其子类。
然而,直接在泛型类内部尝试向泛型类型的列表添加具体类型对象(如SpecialItem
)而不进行显式类型转换,会导致编译错误,因为编译器无法确保这个操作对所有可能的T都是类型安全的。
解决这个问题的一个方法是你已经提到的,即进行显式的类型转换,但这通常被视为一种不理想的解决方案,因为它可能会抑制潜在的类型安全警告,并且如果T不是SpecialItem
的超类,运行时会抛出ClassCastException
。
更好的做法是利用泛型的边界限制来确保只有当T是AbsTask
或其子类时,AbsQueue
才能被实例化。然后,你可以安全地将SpecialItem
添加到列表中,因为你知道T至少是AbsTask
。这里是如何修改你的代码:
import java.util.List;
import java.util.ArrayList;
public class SimpleTest {
abstract class AbsTask {}
abstract class AbsQueue<T extends AbsTask> {
private List<T> lst = new ArrayList<>();
public void addSpecialItem() {
lst.add(new SpecialItem()); // Now this is safe because T must be AbsTask or its subclass
}
}
class SpecialItem extends AbsTask {}
}
在这个修改后的版本中,AbsQueue
定义为AbsQueue<T extends AbsTask>
,这意味着T必须是AbsTask
或其子类。这样,在addSpecialItem
方法中添加SpecialItem
对象就是类型安全的,不需要显式类型转换,因为现在可以确定任何AbsQueue
实例的lst列表能够接受AbsTask
及其子类的实例。