java - Accssesing“嵌套”泛型类型

时间:2012-12-04 16:02:05

标签: java generics

我有两个使用泛型类型(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);
        }
    }
}

它确实有效,但它闻起来不对劲。是否有另一种方法可以使用泛型类型使用另一种泛型类型?

2 个答案:

答案 0 :(得分:1)

使用B<TListItemsType, TContainderType extends A<TListItemsType>>的方式对我来说很好......

这是有道理的原因是您的B类现在确实需要两个参数来描述它:TListItemsTypeTContainderType。实际上,您甚至在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);
        }
    }
}

所以这一切都取决于你需要做什么。你的例子做得不多,所以可以从中删除很多东西,但这可能不是你真正需要的东西。