java - 无法理解泛型和继承
问题描述
当谈到泛型和继承时,我有点纠结。总体思路是一个构建器模式,用于各种组件和包含其他组件的组或容器组件。一些组件组需要特定的组件,一些可以是任何组件。这就是问题所在。我认为最好用代码解释:
public abstract class AbstractGroupComponentBuilder <T extends ComponentGroup<R>, R extends AbstractDashboardComponent> implements ComponentBuilder<ComponentGroup<R>> {
private List<ComponentBuilder<R>> children;
protected void child(ComponentBuilder<R> builder){
children.add(builder);
}
...
}
public class ComponentGroupBuilder extends AbstractGroupComponentBuilder<ComponentGroup<AbstractDashboardComponent>, AbstractDashboardComponent>{
public <T> TableBuilder<T> table(Class<T> clazz){
TableBuilder<T> builder = new TableBuilder<T>(clazz);
child(builder); // PROBLEM HERE: The method child(ComponentBuilder<AbstractDashboardComponent>) in the type AbstractGroupComponentBuilder<ComponentGroup<AbstractDashboardComponent>,AbstractDashboardComponent> is not applicable for the arguments (TableBuilder<T>)
}
...
}
public class TableBuilder<T> implements ComponentBuilder<Table> {
...
}
public class Table extends AbstractDashboardComponent{
...
}
public class ComponentGroup<T extends AbstractDashboardComponent> extends AbstractDashboardComponent {
...
}
public interface ComponentBuilder<T extends AbstractDashboardComponent> {
public T build();
}
所以编译器的错误是:"The method child(ComponentBuilder<AbstractDashboardComponent>) in the type AbstractGroupComponentBuilder<ComponentGroup<AbstractDashboardComponent>,AbstractDashboardComponent> is not applicable for the arguments (TableBuilder<T>)"
为什么不兼容,因为TableBuilder<T> extends ComponentBuilder<Table>
和'Table extends AbstractDashboardComponent'。
解决方案
在这里,您的构建器是TableBuilder<Table>
. 这与ComponentBuilder<AbstractDashboardComponent>
. 问题不是ComponentBuilder
,是里面的东西<>
。与普通类型不同,side 中的内容<>
是不变的,这意味着类型必须完全匹配,不允许子类型。
原因如下:我将使用非常简单和熟悉的类型来解释它:
List<Integer> ints = new ArrayList<Integer>();
List<Number> numbers = ints; // PROBLEM LINE
numbers.add(5.0);
ints.get(0); // uhoh - that's a double and not an int!
标记的行PROBLEM
?那不会编译。修复是这样的:
List<Integer> ints = new ArrayList<Integer>();
List<? extends Number> numbers = ints; // this is fine
numbers.add(5.0); // PROBLEM LINE
ints.get(0); // uhoh - that's a double and not an int!
在此示例中,错误出现在第三行:您不能将ANYTHING添加到List<? extends NothingYouTypeHereCanFixThat>
(不相关的详细信息:除了文字null
)。
这就是为什么第 2 行现在很好的原因。
你需要做同样的事情并扔一些东西? extends
直到它编译。
<T>
= 不变的;只有精确的 T 可以解决,但您可以以任何您想要的方式使用 T。
<? extends T>
=协变;T 或 T 的任何子类型都可以,但您只能调用 get 样式的方法。
<? super T>
=逆变;T 或 T 的任何 SUPERTYPE 都可以,但你只能调用 add 样式的方法(你可以调用 get,但你只会得到 Object)。
逆变很少出现。它让您可以:
List<? super Integer> list = ...;
list.add(5); // compiles fine.
Object o = list.get(0); // all you get is `Object` here.
如果你有一个List<Number>
,你可以将它分配给列表变量。
推荐阅读
- single-sign-on - 不同环境的单点登录服务 URL
- xmpp - 无法使用 Adium 连接到 ejabberd 服务器
- javascript - 重新绘制 xAxis 坐标
- python - Python库安装问题(通过pip install)
- angular - 选择角度垫选择选项时如何停止传播?
- angular - 角度html中的箭头函数
- sql-server - 将 LINQ to SQL 连接到数据库项目而不是物理数据库?
- android - 在微调器中显示 Firebase 数据
- scala - Scala过滤器内部布尔值的未来以进行理解
- java - 在 pom 中使用 maven-install-plugin 将外部库导入本地存储库