Types of Java Generics and Arrays

Inclusion into the problem with generics and array types that I cannot solve. It comes down to that. In the following code, how can I convert a general list to an array of the same generic type using the factory ("T convert (String value)") method to convert each individual element of an input shared list:

@Test public void test(){ List<String> integers = Arrays.asList("1", "2", "3", "4"); Integer[] integerArray = new TypeConverter<Integer[]>(Integer[].class).convert(integers); assertEquals(4, integerArray.length); assertEquals(1, integerArray[0].intValue()); assertEquals(2, integerArray[1].intValue()); assertEquals(3, integerArray[2].intValue()); assertEquals(4, integerArray[3].intValue()); } public class TypeConverter<T>{ Class<T> type; public TypeConverter(Class<T> type) { this.type = type; } T convert(List<String> values){ List output = new ArrayList(); for (String value : values) { //have to use Object.class here since I cant get the non-array type of T: output.add(new TypeConverter(type.getComponentType()).convert(value)); } return (T) output.toArray(); } T convert(String value){ //convert to an int; if(type == Integer.class){ return (T) new Integer(Integer.parseInt(value)); } return null; } } 

As you can see, my naive approach was to simply use the toArray method and make the result as follows:

 (T) value.toArray() 

but this throws a ClassCastException:

java.lang.ClassCastException: [Ljava.lang.Object; cannot be applied to [Ljava.lang.Integer

Is there a way to solve this problem that I do not see, or should I use a different approach?

Edit

Here is the specific code I'm trying to fix. In particular, the visitArray () method:

https://github.com/johncarl81/transfuse/blob/master/transfuse/src/main/java/org/androidtransfuse/analysis/adapter/AnnotationTypeValueConverterVisitor.java

+4
source share
5 answers

You can use an alternative version of List.toArray , which takes as an argument the type of array you want to receive.

toArray method

You can create an empty array using some method of the Array class.

Array.newInstance

So, having the expected type, you just use Array.newInstance(type, 0); and pass the result to the toArray method.

Edit: Since your generic type is an array, you need to get the component type, try the following:

 Object[] array = (Object[]) Array.newInstance(type.getComponentType(), 0); return (T) output.toArray(array); 

Your value conversion method has something that I will let you know how to solve :)

Hurrah!

+2
source

Do not try to use T , try casting to T[] , as you are processing the array T.

+2
source

I suggest cutting reflective and reference arrays.

Slightly abusive inheritance:

 public abstract class StringConverter<T> { public List<T> convert(List<String> values) { List<T> output = new ArrayList<>(); for (String value : values) { output.add(convert(value)); } return output; } public abstract T convert(String value); } public static StringConverter<Integer> toInteger() { return new StringConverter<>() { public Integer convert(String value) { return Integer.parseInt(value); } }; } 
+2
source

This works for me:

 import java.util.*; import java.lang.reflect.*; public class Foo { public static void main(String[] args) { new Foo().test(); } public void test(){ List<String> integers = Arrays.asList("1", "2", "3", "4"); Integer[] integerArray = new TypeConverter<Integer>(Integer.class).convert(integers); System.out.println(Arrays.deepToString(integerArray)); } public class TypeConverter<T>{ Class<T> type; public TypeConverter(Class<T> type) { this.type = type; } T[] convert(List<String> values){ List<T> output = new ArrayList<>(); for (String value : values) { output.add(convert(value)); } return output.toArray((T[]) Array.newInstance(type, output.size())); } T convert(String value){ if(type == Integer.class){ return (T) new Integer(Integer.parseInt(value)); } else if(type == Long.class){ return (T) new Long(Long.parseLong(value)); } return null; } } } 
+1
source

return (T) values.toArray(); should be return (T)output.toArray( new Integer[0])

no, you need to hard code the new Integer[0]

0
source

Source: https://habr.com/ru/post/1413204/


All Articles