This question is in response to another question by opensas: building a generic initializer function in java
From his question it became clear that he needs to convert from any data type T1 to another type T2. When I say “data type” here, I mean types limited to those commonly used to represent raw data: Integer, String, Date, etc. For the purpose of this question we can consider primitives to be boxed.
I’m wondering if there is any API that supports conversion between types where both the input and output are generalized to a set of supported data types. I had a look at Apache Commons’ beanutils.converters package, but there’s a separate converter class for each known input. I’m looking for any functionality that implements something like the following signature:
static <IN, OUT> OUT convert(IN value, Class<OUT> targetType);
or else
static <IN, OUT> OUT convert(IN value, OUT defaultValue);
It really wouldn’t be too hard to implement this kind of mapping oneself, either using a bunch of else if blocks pointing to the various Commons Converters, or else a Map<Class<?>, Converter> for the same purpose. But I’m wondering if this kind of functionality is supported somewhere.
Also, if this winds up being a duplicate I apologize. I tried finding similar questions and was surprised when I found none matching this situation.
EDIT: so an example of this code in action would be:
Integer i = GenericConverter.convert("123", Integer.class); //returns 123
Date d = GenericConverter.convert(1313381772316L, Date.class); //returns today's date
Boolean b = GenericConverter.convert(0, Boolean.class); //returns false
Long l = GenericConverter.convert("asdf", Long.class); //RuntimeException
UPDATE: The BalusC code I linked falls close to the mark, and Bohemian’s answer is a nice lightweight solution (although it doesn’t work for Boolean conversions). He’s also right that Dates should be probably be handled separately if we want to generalize conversion of these other data types. I’m still hoping for additional answers though – especially if there is more of a hands-off API available somewhere.
In JDK 8 this can be easily implemented with the new
java.util.functions.Mapperinterface and a lambda expression.Using method references it can be even simpler:
Or things like:
Or cool conversions like:
In the current implementation of the JDK8 API, a few default mappers have been defined (i.e.
LongMapper,IntMapper,DoubleMapper) and there’s a utility class calledMappersthat defines some others like a string mapper, and identity mapper, a constant mapper, etc.I am not sure if this is what you are after, but certainly it must be a nice way to implement it.
Cases like the one you suggest for:
Can be implemented with the
Mappersutility class:And your signature:
Could be implemented with something like:
As such, a code like this…
Would yield:
[0, 0, 2, 0, 4, 0, 6]