2014-10-30 17 views
7

Java 8'in yeni akışlarını içeren bir proje üzerinde çalışırken, bir akışta Stream#toArray()'u aradığımda, T[] yerine Object[] döndürdüğünü fark ettim. Olduğum gibi, Java 8'in kaynak koduna girmeye başladım ve Object[] toArray();'u neden T[] toArray(); olarak kullanmadıklarını bulamadım. Bunun arkasında herhangi bir muhakeme var mı, yoksa sadece bir tutarlılık mı?Yeni Java 8 akışları neden bir Array Dizisi'ni Array aramalarına döndürüyor?

DÜZENLEME 1: Bir çok insanın bunun mümkün olmayacağını söyleyen yanıtlarda farkettim, ancak bu kod pasajı beklenen sonucu derleyip geri getiriyor?

import java.util.Arrays; 

public class Test<R> { 

    private Object[] items; 

    public Test(R[] items) { 
     this.items = items; 
    } 

    public R[] toArray() { 
     return (R[]) items; 
    } 

    public static void main(String[] args) { 
     Test<Integer> integerTest = new Test<>(new Integer[]{ 
      1, 2, 3, 4 
     }); 

     System.out.println(Arrays.toString(integerTest.toArray())); 
    } 

} 
+2

R'yi nasıl bilebilir? Belirli türlerin döndürülmesini istiyorsanız, bir jeneratöre yönteme geçin. Örneğin, bir String dizisi için aşağıdakileri yapın: 'streamString.toArray (String [] :: new)' – meskobalazs

+0

'R', Akış arabiriminin type parametresidir. Soruma "R" kullandım, ama "T" olmalı. Bunu günceller. – Martijn

+0

@meskobalazs Ancak yine de, en kötü durum senaryosunu istediğiniz türe çevirebilirsiniz. Yazılan yol yerine neden joker yolunu seçmeyi tercih ettiler? Bazen, programcıya hangi tip akışın böyle bir durumda sahip olduğunu bilmediğini, en iyi kod için geçerli olmadığını hissediyorum. Ve akım hala tam olarak ne tür içerdiğini bilen biridir. – Martijn

cevap

8

Bu, List#toArray()'un sahip olduğu aynı sorundur. Tip silme, geri dönmemiz gereken dizi türünü bilmemizi engeller. bakılmaksızın döküm aşağıdaki

class Custom<T> { 
    private T t; 
    public Custom (T t) {this.t = t;} 
    public T[] toArray() {return (T[]) new Object[] {t};} // if not Object[], what type? 
} 

Custom<String> custom = new Custom("hey"); 
String[] arr = custom.toArray(); // fails 

bir Object[] birine atanamıyor bu nedenle bir String[]ve düşünün. Aynı fikir Stream ve List için geçerlidir. Aşırı yüklenmiş toArray(..) yöntemini kullanın.

+0

Düzenlememe bak. Bunun neden işe yaradığını açıklar mısın? – Martijn

+1

Kodunuz gayet iyi çünkü 'item'' aslında bir 'Tamsayı []' değil, başka bir şeye dönüştürülen '' '' '' '' '' '' ''. –

+2

@MartijnRiemers Örneğinizde, önceden oluşturduğunuz diziyi döndürüyorsunuz (bunun için türünü biliyorsunuz). Bir "Akış" (veya bir "Liste") bir dizi tarafından desteklenecek şekilde garanti edilmez. Başka herhangi bir yolla inşa edilebilir. Bu, bir ** yeni ** dizisinin yaratılması gerektiği anlamına gelir, ancak hangi türün olduğunu bilemeyiz. –

5

toArray() neden Object[] değerini döndürmesi hakkında: bu tip silme nedeniyle. Genel türler, çalışma zamanında tür parametrelerini kaybeder, bu nedenle Stream<Integer>, Stream<String> ve Stream aynı türler olur. Bu nedenle, oluşturulacak dizinin bileşen türünü belirlemenin bir yolu yoktur. Aslında, yansıma kullanarak dizi öğelerinin türlerini analiz edebilir ve daha sonra least upper bound bulmaya çalışabilir, ancak bu çok karmaşık ve yavaştır.

R[] dizisini aşırı yüklenmiş toArray(IntFunction<A[]> generator) yöntemiyle elde etmenin bir yolu vardır. Bu yöntem, arayan kişiye dizinin türünü seçme fırsatı verir. Kod örnekleri için şu soruya bakın: How to Convert a Java 8 Stream to an Array?.

18

Dene:

String[] = IntStream.range(0, 10).mapToObj(Object::toString).toArray(String[]::new); 

no-arg toArray() metodu sadece bir nesne [] döner ancak size (uygun şekilde, bir dizi yapıcı referans olarak temsil edilebilir) bir dizi fabrika başarılı olursa, İstediğiniz (uyumlu) türden alabilirsiniz.

+0

Bu doğrudan OP'nin sorusunu ele almasa da, aradığım cevap budur. –