2014-11-30 25 views
6

Genellikle, değişkenlerin uygulama sınıfı değil, bazı arabirimlerle bildirilmesi gerektiği önerilmektedir.Değişkenler her zaman Java arayüzünde belirtilmelidir?

List<Integer> list = new ArrayList<>(); 

Ancak, gerçekten O bir ArrayList (örn Fisher-Yates üreticimizin) (1) rasgele erişim bağlıydı bir algoritma için bu listeyi kullanıyorum ki: Örneğin. Bu durumda, ArrayList'un benim için temsil ettiği anahtar soyutlama, onun sadece Doğa niteliğini değil, diziliş niteliğindeki doğasıdır. Diğer bir deyişle, birisi list'u LinkedList olarak değiştirmiş ve değiştirmiş olsa bile, kod derlenmiş olsa bile bu sorun yaratabilir. Böyle bir durumda, beyan ben arayüzlerini kullanarak hala çok önemli olduğunu düşünüyorum uygulama tipini ?, ör .:

ArrayList<Integer> list = new ArrayList<>(); 
+2

List/ArrayList başvurusunu bir genel API aracılığıyla açığa çıkarmazsanız, gerçekten önemli değildir (diğer tüm durumlarda olduğu gibi, modern bir IDE, bir türden diğerine yeniden sıralama yapmak için önemsiz hale getirmelidir). Yani en uygun olanı yapın. –

+0

Beklediğiniz verinin büyüklüğüne bağlı olarak, bir List kabul edebilir ve ardından rastgele erişimi garanti altına almak için fonksiyonunuzun içindeki bir ArrayList'e kopyalayabilirsiniz. –

cevap

3

Oliver Charlesworth'un yorumda ne söylediğini vurgulamak için: Bu bilginin kamuya açık olup olmadığı en önemli farktır.

Sorunun nasıl yazıldığından itibaren, bir alanı (ve bir yöntem parametresi veya dönüş değeri değil) hakkında konuşuyorsunuz gibi görünüyor. Ve özel bir alan, tanım başına, bir uygulama detayıdır ve ,'u isteğe özgü hale getirebilir. Bu yüzden, ArrayList olarak ilan etmek mümkün olacaktır - kesinlikle konuşmak gerekirse, bu konuyla ilgili değildir. ifade bu şekilde Kime: Sen ...

dan beyanı değiştirebilir biri birileri ... Bir LinkedList için list değişirse

, bu sorunlu olacağını söyledi

private List<T> list = new ArrayList<T>(); 

için

private List<T> list = new LinkedList<T>(); 

can als o

private LinkedList<T> list = new LinkedList<T>(); 

için örneğin bir açıklama, bu (önemli) uygulaması detay eklemek olacaktır Bunu engellemenin tek pratik yolu

private ArrayList<T> list = new ArrayList<T>(); 

dan beyanı değiştirmek

/** 
* The list that stores ... whatever. 
* 
* This list should have a complexity of O(1) for random access, 
* because ... 
*/ 
private final List<T> list = new ArrayList<T>(); 

(bu, aynı zamanda, dahili bir RandomAccess olmasını bekler bir yönteme listesini geçirilerek yürütülebilir. Bu AlexR tarafından önerilen, ancak public yöntemlere atıfta. private yöntemleri için bile bu olmaz niyeti ve nedenleri belgelenmemişse, yöntem imzasını değiştirmesini engelleyin.

+0

Ne demek "kesinlikle konuşuyoruz, bu uygun değil"? – PeteyPabPro

+0

@PeteyPabPro Listeyi "ArrayList" olarak bildirmenin herhangi bir yarar getirmediğini kastediyorum. Burada oluşturulan * örnek * türünü değiştirebilen herkes, * değişkeninin * türünü de değiştirebilir. (Bir yarar getirmediğini, ancak potansiyel (küçük) bir dezavantaja sahip olmadığını, yani * ArrayList öğesinden * örneğini * değiştirmek istediğinizde değişkenin bildirimini değiştirmeniz gerektiğini unutmayın. (1) Örneğin, bir "ArrayList" değil, bir "CopyOnWriteArrayList" de kullanabilirsiniz, ancak hala O (1) var ve bu yüzden de burada olur.) – Marco13

+0

İki avantaj görüyorum. 1) Bir belge formu olarak hizmet eder ve 2) Herhangi bir nedenle, ArrayList olarak Listenin örneklerini LinkedList'e geçirmek için bazı otomatik yeniden işlemeyi yapmak istediyse, ArrayList olarak bildirilen değişkenin geliştiricinin bilmeden O'nun (1) gereksinim. – PeteyPabPro

2

kullanmasını sağlamak için Tamam kabul olduğunu. Durum çok özel ama somut sınıfların kullanımı olmadan onu çözmenin bir yolu var. RandomAccess adlı bir arayüz var. Bu, yöntemleri bildirmeyen bir etiket arabirimidir, ancak, elemanlara randome erişimi sağlayan uygulayıcılar veya List tarafından kullanılmalıdır.

public <E, L extends List<E> & RandomAcess>void algorithm(L list); 

Bu yöntemle bağlantılı liste geçmek mümkün olmayacaktır, ancak ArrayList çalışacaktır:

Yani, aşağıdaki gibi rasgele erişim listesi gerektirir yönteminizi tanımlayabilirsiniz. Şimdi beklediğiniz gibi, algoritmanızı değiştirmeden listenin kullanımını değiştirebilirsiniz. Örneğin,numaralı iplik güvenliğini kullanarak, açık bir şekilde syncrhonized ifadeleri olmadan çok iş parçacıklı işlenmeyi gerçekleştirebilirsiniz.

+0

Ama buna geçtiğim liste, "Liste" değil, "ArrayList" türüne sahip olmalıdır, bu yüzden beyannamede somut sınıflardan kaçınmam için bana izin vermiyor gibi görünmektedir. – PeteyPabPro

+0

"ArrayList" yöntemini yönteminize iletmeniz iyi bir şeydir. Ancak yöntem önerdiğim şekilde tanımlanmışsa, yöntemi değiştirmeden geçtiğiniz liste türünü değiştirebilirsiniz. – AlexR

İlgili konular