我决定在我的设计中使用泛型,效果很好。只有当我达到抽象时,我才陷入困境。我正在收集使用不同泛型实现相同接口(interface)的不同实例。据我所知,为了将它们保存在列表中,我需要使用通配符。所以我当前的代码是这样的:
import java.util.List;
import java.util.ArrayList;
public class Main {
private List<IView<?>> views = new ArrayList<IView<?>>();
public void addView(IView<?> view)
{
this.views.add(view);
}
public void handle()
{
for (IView<?> view : this.views)
{
// ## ERROR ##
view.render(
view.cast(new Object())
);
}
}
}
public interface IView<T> {
public T cast(Object entity);
public void render(T entity);
}
public class FirstView implements IView<One> {
// .. Added to Main-collection views
}
public class SecondView implements IView<Two> {
// .. Added to Main-collection views
}
我还尝试了另一种方法,从 IView 返回一个类,然后用它来调用 class.cast。同样的问题。
编译器不接受这个 - IView(Capture#2-of ?) 类型中的 Render(Capture#2-of ?) 方法不适用于参数 (Capture#3-of ?)。
我部分地认为理解这个问题,但我看不到解决它的方法。如果有人能帮助我重新开始,我将非常感激。
最佳答案
我不相信你可以给 ?
赋值“类型化”变量。一个无限的“?”意味着“变量的原始类型未知”,这意味着没有已知类型可以安全地分配给它。这并不意味着在运行时检索类型参数的实际值。
使用泛型方法进行强制转换的整个想法在 Java 泛型中没有意义。以类型安全的方式对未知类型对象进行强制转换的唯一方法是使用实际强制转换。
唯一的解决方案是摆脱cast()方法,并使用原始类型:
public void handle()
{
for (IView view : this.views)
{
view.render(new Object());
}
}
假设cast()方法只进行类型转换,不进行类型转换。如果最终调用的实现方法是 FirstView.render(One object),我相信 Java 实际上会将参数强制转换为 One。 (这也可能导致有趣的错误,即在没有强制转换的代码行上抛出 ClassCastException。)
如果cast()
可以进行类型转换(在这种情况下,“cast”对于该操作来说是一个坏名字),这意味着每个 IView 必须 能够接受 Object,在这种情况下它并没有多大用处sense 的参数为render()
首先是泛型类型。我将使用的设计如下所示:
interface IView<T> {
void renderObject(Object o);
void render(T);
T coerce(Object o);
}
abstract class ViewBase<T> implements IView<T> {
void renderObject(Object o) {
render(coerce(o));
}
}
class FirstView extends ViewBase<One> {
// …
}
封装“cast”操作。
没有静态类型安全的方法来处理不同类型的对象集合 - 在 Java 中,IView<One>
和IView<Two>
类型与 String
不同和Integer
并且两者之间不存在安全转换。
关于java - 如何动态转换/确保具有不同泛型的集合的类型安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7585054/