2012-08-15 77 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,但我仍然認爲類型本身給了程序員足夠的警告。此外,最好冒險改變這個類的人引入一個類型錯誤,而不是讓它只取一個通用數組,並冒任何調用者犯類型錯誤的風險。