Why do new Java 8 threads return an Object Array to toArray calls?

While I was working on a project using the new Java 8 threads, I noticed that when I called Stream#toArray() on the stream, it returns Object[] instead of T[] . Surprised, like me, I started digging into the Java 8 source code and could not find the reasons why they did not implement Object[] toArray(); like T[] toArray(); . Are there any considerations behind this, or is it just (in) consistency?

EDIT 1: I noticed in the answers that many said it would not be possible, but this piece of code compiles and returns the expected result?

 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())); } } 
+7
java java-8
source share
3 answers

This is the same problem as List#toArray() . Erasing types does not allow us to find out the type of array that we need to return. Consider the following

 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 

An Object[] not a String[] and therefore cannot be assigned to one, regardless of the actor. The same idea applies to Stream and List . Use the overloaded toArray(..) method.

+8
source share

Try:

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

The no-arg toArray () method will just return Object [], but if you pass in a factory array (which can be conveniently represented as a reference to an array constructor), you can get any (compatible) type that you like.

+18
source share

About the reason why toArray() returns Object[] : this is due to type erasure. Generic types lose their type parameters at runtime, so Stream<Integer> , Stream<String> and Stream become the same types. Therefore, there is no way to determine the type of component array being created. In fact, you can analyze the types of array elements using reflection, and then try to find their smallest upper bound , but this is too complicated and slow.

There is a way to get the R[] array using the overloaded method toArray(IntFunction<A[]> generator) . This method gives the caller the choice of array type. See this SO question for code examples: How to convert a Java 8 stream to an array? .

+5
source share

All Articles