关于java:通用类型创建者

Generic type creator

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Java Generics: Cannot cast List to List?

我想在一些创建继承类的基类上创建函数。

我已经尝试过了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class BaseFormat
{
    // Some variables

    public BaseFormat(string txt)
    {
        // Do something
    }

    public static <T> ArrayList<T extends BaseFormat> getTextFormat(String[] txt)
    {
        ArrayList<T> list = new ArrayList<T>();
        for (int i = 0; i < txt.length; i++)
        {
            list.add(new T(txt[i])); // ERROR
        }
        return list;
    }
}

class FooFormat extends BaseFormat
{
    // Some variables

    public FooFormat (string txt)
    {
        // Do something
    }
}

而这:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class BaseFormat
{
    // Some variables

    public BaseFormat(string txt)
    {
        // Do something
    }

    public static ArrayList<BaseFormat> getTextFormat(String[] txt)
    {
        ArrayList<T> list = new ArrayList<T>();
        for (int i = 0; i < txt.length; i++)
        {
            list.add(new BaseFormat(txt[i]));
        }
        return list;
    }
}

但当我尝试强制转换数组时,会收到一个错误。这是我的代码:

1
2
String[] txts = ...; // Some texts
ArrayList<FooFormat> list = (ArrayList<FooFormat>) BaseFormat.getTextFormat(txts); // Casting ERROR

那么我该怎么做,但仍然保持它的通用性呢?


您必须将类型作为参数传递给静态方法,然后可能使用反射来调用Class.newInstance。类型擦除意味着编译后您将没有一个具体的类型T,所以您不能编译new T(...)


因此,您将允许动态类型化的泛型与允许重写方法的继承混合在一起。您真正想要的是将创建包装字符串与创建列表分开。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class BaseFormat
{
  // derived classes override this method to provide their own implementations
  public abstract BaseFormat wrapText(String[] txt);

  public ArrayList<? extends BaseFormat> getTextFormat(String[] txt)
  {
    ArrayList<? extends BaseFormat> list = new ArrayList<BaseFormat>();
    for (int i = 0; i < txt.length; i++)
    {
        list.add(wrapText(txt);
    }
    return list;
  }
}


你想做如下的事吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
class BaseFormat { }

class FooFormat extends BaseFormat { }

class FormatUtils {
    public static <T extends BaseFormat> List<T> getTextFormat(String[] txt, Class<T> clazz) {
        List<T> list = new ArrayList<T>();
        //...
                T t = clazz.newInstance(); //create instance using reflection
                //...
        return list;
    }
}

并且做

1
List<FooFormat> list = FormatUtils.getTextFormat(new String[]{}, FooFormat.class);


试着做

1
  ArrayList<BaseFormat> list = (ArrayList<BaseFormat>) BaseFormat.getTextFormat(txts);

然后,在迭代时,可以通过检查instanceof运算符将项向下强制转换为fooformat。