2017-03-04 20 views
6

(Java): Bu kod ile ana danDönüş tip I Bu genel fonksiyonu var

public static <T extends Number> T sum(List<T> list){ 
    Number tot = 0; 
    for(Number n: list){ 
     tot = tot.doubleValue() + n.doubleValue(); 
    } 
    return (T)tot; 
} 

hatırlayın:

public static void main(String[] args) { 
    ArrayList<Integer> listInt = new ArrayList<>(); 
    listInt.add(3); 
    listInt.add(5); 
    listInt.add(6); 
    listInt.add(8); 
    System.err.println("Sum: " + Calcolatrice.sum(listInt)) 
} 

Bu nedenle (listInt tamsayılar, bir ArrayList olmak üzere) bekliyoruz işlev toplamı tarafından döndürülen değer T = Tamsayıdır ve bu durumda, Double'den Integer'e bir dönüşüm hatası verir. Sonuç türü, bunun yerine Çift'tir ve hiçbir hata atılmamıştır. Döküm (T) totunun istenen sonucu yoktur.

Sanırım Java, jenerik duruş aşamasını ele alıyor, ama birisi neden bu şekilde çalıştığını daha iyi açıklıyor?

+4

[tür silme] (https://docs.oracle.com/javase/tutorial/java/generics/erasure.html) davranışı açıklayan terimdir .... –

cevap

1

Calcolatrice.sum(listInt) ait dönüş tipi aslında örnekte sum sonunda döküm için Integer sayesindedir. Ancak sonucun gerçek tipi Double'dur. Açıkçası bu iyi bir durum değil, fakat açıkçası derleyiciye, dönüş değerinin dönüş değeriyle aynı türde olacağını açıkça söylediniz.

Bu durum yerine Calcolatrice.sum(listInt).toString() yazmak için olsaydı bir Double üzerinde Integer.toString() arar ki çünkü bir ClassCastException: java.lang.Double cannot be cast to java.lang.Integer alacağı anlamına gelir. Kodunuzun aslında ne yaptığı System.out.println("Sum: "+ String.valueOf(Calcolatrice.sum(listInt))), Object (bu nedenle çakışmayı çözerek) toString numaralı telefonu aramadan önce çalışıyor.

@TmTron, Double ve Integer kutulu tiplerde ilkellerle aynı şekilde yayınlayamayacağınızı belirtir.

yani

int i = (int) 2.0; 

farklı kurallar aşağıdaki gibidir:

Integer i = (Integer) new Double(2.0) 
3

Generics yalnızca kodunuzda hata yapmadığınızdan emin olmak için derlemede kullanılır: Burada parametre List<T> ve alma değişkeni T türünde olmalıdır. Bu kadar.

Çalışma zamanı içinde, T mevcut değil ve tot, T; Number.

Tanımlanmamış örnekleri almak için yönteminizin içinde T yöntemini kullanabilirsiniz, ancak örneğin, new T() yapamazsınız. Eğer tip hiyerarşisi baktığımızda

3

Eğer Integer ve Double hem Number çocukları olduğunu görüyoruz: bu yüzden kardeşler ve doğrudan Integer için Double döküm olamaz:

Double testDbl = 3.14; 
    Integer testInt = (Integer)testDbl; // this will NOT compile 

derleyici kesin bilemeyiz, senin sum işlevin dönüş deyiminde dökme çalışmak veya başarısız olur ise: ama derleyici bir uyarı gösterecektir:

Unchecked cast: 'java.lang.Number' to 'T' 

Çünkü (T)tot sert dökümden derleyici, işlevinizin bir Integer döndürdüğü için onu alacaktır (ki öyle değil).

Son olarak, type erasure nedeniyle, çalışma zamanı denetimi yok.

İlgili konular