我有两个使用泛型类型(A,B)的类。 我的问题是 - 从B内部使用第一个通用类型(TA)的最佳方法是什么? 这是一个简化的例子:
public class A<TListItemsType>
{
List<TListItemsType> list = new LinkedList<TListItemsType>();
public List<TListItemsType> getList()
{
return list;
}
}
public class B<TContainderType extends A>
{
TContainderType temp = null;
public B(TContainderType cont)
{
temp=cont;
}
public void DoWork()
{
for (TListItemsType item : temp.getList())
{
System.out.println(item);
}
}
}
我尝试过建议的解决方案here -
public class B<TContainderType extends A<TListItemsType>>
{
TContainderType temp = null;
public B(TContainderType cont)
{
temp=cont;
}
public void DoWork()
{
for (TListItemsType item : temp.getList())
{
System.out.println(item);
}
}
}
只要使用预定义类型(如Integer或String),它就可以正常工作,遗憾的是,这不起作用,因为编译器不会将泛型识别为类名。
所以进一步尝试配置另一个泛型类型,然后在extends:
中使用它public class B<TListItemsType, TContainderType extends A<TListItemsType>>
{
TContainderType temp = null;
public B(TContainderType cont)
{
temp=cont;
}
public void DoWork()
{
for (TListItemsType item : temp.getList())
{
System.out.println(item);
}
}
}
它确实有效,但它闻起来不对劲。是否有另一种方法可以使用泛型类型使用另一种泛型类型?
答案 0 :(得分:1)
使用B<TListItemsType, TContainderType extends A<TListItemsType>>
的方式对我来说很好......
这是有道理的原因是您的B
类现在确实需要两个参数来描述它:TListItemsType
和TContainderType
。实际上,您甚至在TListItemsType
内的DoWork()
函数中明确使用了B
。因此,您需要将其作为参数传递,这是公平的。否则,编译器甚至不会知道你在DoWork()
函数中的意思,因为你也可以像这样编写类定义:
public class B<TWorkItemType, TContainderType extends A<TWorkItemType>>
{
//...
public void DoWork()
{
for (TWorkItemType item : temp.getList())
{
System.out.println(item);
}
}
}
(请注意,我完全重命名了该类型,但只在B
,而不在A
!)
如果它只是要求您使用与TListItemsType
定义中使用的名称A
相同的名称,那么您在使用泛型时可能会遇到的问题非常有限。例如,您无法接受一种类型extends List<E>
而另一种类型扩展Enum<E>
,因为这两种类型都使用<E>
作为其通用标识符。
我希望现在闻起来更好......:)
答案 1 :(得分:0)
从您的问题中,您真正不清楚需要什么样的要求,以及使用TListItemsType需要什么。如果你真的不需要以有意义的方式使用TListItemsType(就像在你的例子中一样),你可以消除它,只需要TContainderType扩展A<?>
:
public class B<TContainderType extends A<?>>
{
TContainderType temp = null;
public B(TContainderType cont)
{
temp=cont;
}
public void DoWork()
{
for (Object item : temp.getList())
{
System.out.println(item);
}
}
}
就此而言,如果您不打算返回TContainderType或在类型参数中使用它,您甚至可以消除它:
public class B
{
A<?> temp = null;
public B(A<?> cont)
{
temp=cont;
}
public void DoWork()
{
for (Object item : temp.getList())
{
System.out.println(item);
}
}
}
所以这一切都取决于你需要做什么。你的例子做得不多,所以可以从中删除很多东西,但这可能不是你真正需要的东西。