0

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

我已经尝试过这里建议的解决方案-

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 之类的预定义类型,它就可以工作,遗憾的是,这不起作用,因为编译器无法将泛型识别为类名。

所以继续尝试配置另一个泛型类型,然后在扩展中使用它:

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);
        }
    }
}

它确实有效,但味道不对。是否有另一种方法可以使用另一个泛型类型使用的泛型类型?

4

2 回答 2

1

The way you did it using B<TListItemsType, TContainderType extends A<TListItemsType>> looks good to me...

The reason this makes sense is that your B class now indeed needs two parameters to describe it: TListItemsType and TContainderType. In fact, you are even using TListItemsType explicitly in your DoWork() function inside B. So it's only fair that you need to pass it as a parameter. Otherwise the compiler wouldn't even know what you mean inside your DoWork() function, as you could just as well write the class definition like this:

public class B<TWorkItemType, TContainderType extends A<TWorkItemType>>
{
    //...

    public void DoWork()
    {
        for (TWorkItemType item : temp.getList())
        {
            System.out.println(item);
        }
    }
}

(Notice that I a renamed the type entirely, but just in B, not in A!)

If it simply required you to use the same name TListItemsType as used in the definition of A, you would be quite limited in the things you could do with generics. For example, you could not accept one type extends List<E> and another extends Enum<E>, since both of these used <E> as their generic identifier.

I hope it smells better now... :)

于 2012-12-04T16:20:54.953 回答
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);
        }
    }
}

就此而言,如果您不打算返回 TContainerType 或在类型参数或其他内容中使用它,您甚至可以消除它:

public class B
{
    A<?> temp = null;
    public B(A<?> cont)
    {
        temp=cont;  
    }
    public void DoWork()
    {
        for (Object item : temp.getList())
        {
            System.out.println(item);
        }
    }
}

所以这一切都取决于你需要做什么。您的示例并没有做太多事情,因此可以从中删除很多东西,但这可能不是您真正需要的。

于 2012-12-04T19:41:38.913 回答