Reputation: 9
I already have this code implemented, and it works just fine:
static Integer[] parseInteger(String[] arr){
return Arrays.stream(arr).map(Integer::parseInt).toArray(Integer[]::new);
}
But now I look for something like this:
public <T extends Number> T[] parseString(String[] arr,T n, Class<T> type){
return Arrays.stream(arr).map(T::parseNumber).toArray(T[]::new);
}
Is there any solution for this problem? Didn't find anything.
Upvotes: 0
Views: 854
Reputation: 45005
It cannot work because Number
is an abstract class that doesn't provide any generic method allowing to parse a String
into the corresponding Number
implementation. You will need to provide your own method as next for example:
public class NumberParser {
public static <T extends Number> T parseNumber(String val, Class<T> type) {
if (type == Double.class) {
return (T) Double.valueOf(val);
} else if (type == Float.class) {
return (T) Float.valueOf(val);
} else if (type == Integer.class) {
return (T) Integer.valueOf(val);
} else if (type == Long.class) {
return (T) Long.valueOf(val);
}
throw new IllegalArgumentException("Unknown number type");
}
}
NB: This generic parser is not meant to be perfect, it just shows the idea.
Then your method will be:
public static <T extends Number> T[] parseString(String[] arr, Class<T> type){
return Arrays.stream(arr).map(s -> NumberParser.parseNumber(s, type))
.toArray(length -> (T[]) Array.newInstance(type, length));
}
You will then be able to parse your array of String
generically as next:
String[] values = {"1", "2", "3"};
Integer[] result = parseString(values, Integer.class);
for(Integer i : result) {
System.out.println(i);
}
Output:
1
2
3
Upvotes: 2
Reputation: 82461
T::parseNumber
won't work, since there is no parseNumber
method in Number
. Furthermore there is no inheritance for static
methods. Also e.g. BigInteger
doesn't even offer a static
method for parsing from String
and AtomicInteger
doesn't offer a constructor that takes String
, so even if you use reflection, you won't get it to work with the implementations of Number
in the API, let alone all possible implementations...
T[]::new
doesn't work since you cannot generate a array using a type parameter.
You could change the method to make it work however:
Pass a Function<String, T>
to parse the String
s and either pass a IntFunction<T[]>
to generate the array or use the Array
class (see How to create a generic array in Java?):
public <T extends Number> T[] parseString(String[] arr, Function<String, T> parser, Class<T> type){
return Arrays.stream(arr).map(parser).toArray(size -> (T[]) Array.newInstance(type, size));
}
Sample use
parseString(new String[]{ "1", "10", "193593118746464111646135179395251592"}, BigInteger::new, BigInteger.class)
Upvotes: 2