使用参数调用函数,该参数是参数化对象的数组

时间:2012-08-15 01:35:24

标签: java generics

我有一个扩展PictureArrayAdapter的类ArrayAdapter<Pair<String, ImageInitialiser>>并具有以下构造函数:

public PictureArrayAdaptor(Context context, Pair<String, ImageInitialiser>[] values)

我们已经明确声明,当调用此构造函数时,程序员必须传递Pair<String, ImageInitialiser>[],否则可能会发生类型错误。现在,生成这样一个没有警告的对象是相当困难的:

@SuppressWarnings("unchecked")
Pair<String, ImageInitialiser> tableData[] = new Pair[1];
tableData[0]=new Pair<String, ImageInitialiser>("A", new ResourceImageInitialiser(R.drawable.sample1));

一种可能性是使用列表。但是,为了保持一致性,我想保持所有构造函数完全与基类相同。有没有更好的方法来调用这个构造函数?我真的不认为这是应该怎么称呼的。

3 个答案:

答案 0 :(得分:4)

另一种方法是创建一个扩展Pair的类,例如

class NamedImage extends Pair<String, ImageInitialiser> { ... }
class PictureArrayAdapter extends ArrayAdapter<NamedImage> { ... }

NamedImage现在是可恢复的类型,因此您可以使用NamedImage[]这样的数组而不受惩罚。此外,它消除了未经检查的异常并简化了所有声明,使它们不再具有嵌套类型参数。

答案 1 :(得分:2)

阵列和泛型就像石油和水。使用通用类型的数组来保证类型安全是不可能的,因此警告。 varargs(...)也是如此,因为它涉及隐式数组创建。有关原因的详细说明,请参阅generics FAQ

我强烈建议将参数设为List而不是数组。如果超级构造函数必须采用数组,则可以在toArray上调用List。集合通常比数组更通用,有些人认为除非绝对必要,否则不应再直接使用数组。

答案 2 :(得分:0)

好的,我已经考虑了一段时间了,我意识到我这样做的方式正是这样做的。在涉及通用对象时,列表肯定更好用,但我试图匹配一个接口以保持一致性。

generics tutorial(第15页)解释了我们无法创建泛型对象数组的原因是,这将允许运行时类型错误而不会发出警告。

List<?>[] lsa = new List<?>[10]; // ok, array of unbounded wildcard type
Object o = lsa;
Object[] oa = (Object[]) o;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
oa[1] = li; // correct
String s = (String) lsa[1].get(0); // run time error, but cast is explicit

通过使用@SuppressWarnings("unchecked"),我们强制任何触及此代码的人必须考虑类型安全而不是依赖于编译器。这不是什么大问题,因为像Python这样的语言,根本就没有编译时类型的安全性。 @SuppressWarnings让程序员明白他们必须自己管理它,但即使他们错过了它,它仍然可以在运行时被捕获。

现在,让我们考虑一下构造函数。我认为这将是编译器发出警告的好地方,因为声明泛型数组变量和泛型数组参数之间没有太大区别。在这里,我们没有@SuppressWarnings,但我仍然认为类型本身给程序员足够的警告。此外,最好让某人更改此类引入类型错误,而不是让它只是采用通用数组并冒任何调用者造成类型错误的风险。