0

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.

2 Answers 2

2

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 Strings 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)
Sign up to request clarification or add additional context in comments.

Comments

2

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.