2012-08-15 51 views
3

我有一个类PictureArrayAdapter扩展ArrayAdapter<Pair<String, ImageInitialiser>>并具有以下构造的数组:调用带有参数的函数是parametrised对象

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

一种可能性是使用列表来代替。但是,为了保持一致性,我想让所有构造函数完全相同。有没有更好的方法来调用这个构造函数?我真的不认为这就是它应该被称为的方式。

+0

正在使用'public PictureArrayAdaptor(Context context,Pair ... ... values)'一个选项吗? – dasblinkenlight 2012-08-15 01:38:47

+0

@dasblinkenlight:谢谢。这是一个有趣的想法,但如果我想保持构造函数与基类相同 – Casebash 2012-08-15 01:40:24

+0

我无法确定传递数组代替可变参数列表:'...'是“语法糖”在一个简单的数组之上。 – dasblinkenlight 2012-08-15 01:43:39

回答

4

另一种方法是创建一个扩展对一类,例如现在

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

NamedImage是reifiable类型,因此你可以使用数组一样NamedImage[]而不受惩罚。另外,它可以摆脱未经检查的异常并简化所有声明,从而不再具有嵌套类型参数。

+0

任何机会,你可以得到这个语言,拉哈斯克尔的'newtype'? :) – yshavit 2012-08-15 05:49:39

+0

我不知道,因为我不知道Haskell。 NamedImage是一个真正的类型,但我想有一些样板文件(例如,构造函数)是使其正确工作所必需的。 Java在这个领域最有可能的演变可能是泛化的泛化。对此有一些想法,但没有具体的计划。 – 2012-08-15 06:01:11

+0

Haskell中的'newtype'定义了一个新类型,它的唯一构造函数是旧类型的实例(转换为Java语言),并且只有一个getter。这意味着该类型仅在编译时存在;在运行时,它只是基础类型。虽然可能不会在Java中工作,因为反射的复杂性。 – yshavit 2012-08-15 06:04:12

2

阵列和仿制药就像油和水。用一个通用类型的数组来保证类型安全是不可能的,因此是警告。可变参数(...)也是如此,因为它涉及到隐式数组的创建。有关为什么,请参阅generics FAQ的详细说明。

我强烈建议使参数a List而不是数组。如果超级构造函数必须接受一个数组,您可以拨打List上的toArray。一般来说集合比数组多得多,有些人认为除非绝对必要,否则不应该直接使用数组。

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,但我仍然认为类型本身给了程序员足够的警告。此外,最好冒险改变这个类的人引入一个类型错误,而不是让它只取一个通用数组,并冒任何调用者犯类型错误的风险。