Generic data type conversion method

前端 未结 5 849
走了就别回头了
走了就别回头了 2020-12-25 14:31

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 conve

相关标签:
5条回答
  • 2020-12-25 14:55

    In JDK 8 this can be easily implemented with the new java.util.functions.Mapper interface and a lambda expression.

    Mapper<String,Integer> atoi = s -> Integer.valueOf(s);
    Integer r = atoi.map("10");
    

    Using method references it can be even simpler:

    Mapper<String, Integer> atoi = Integer::new;
    Integer r = atoi.map("10");
    

    Or things like:

    List<Long> dates = asList(1344754620310L,1344754854877L);
    List<Date> asDates = dates.map(Date::new).into(new ArrayList<Date>());
    

    Or cool conversions like:

    List<Integer> myInts = "5,4,3,2,1,0,6,7,8,9"
      .splitAsStream(",")
      .map(Integer::new)
      .into(new ArrayList<Integer>());
    

    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 called Mappers that 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:

    static <IN, OUT> OUT convert(IN value, Class<OUT> targetType);
    

    Can be implemented with the Mappers utility class:

    Mapper<String, Integer> atoi = Mappers.instantiate(String.class, Integer.class);
    Integer r = atoi.map("10");
    

    And your signature:

    static <IN, OUT> OUT convert(IN value, OUT default);
    

    Could be implemented with something like:

    Mapper<String, Integer> atoi = chain(substitute(null, "0"), Integer::new);
    Integer r = atoi.map(null); //produces 0
    

    As such, a code like this...

    List<String> data = asList("0", null, "2", null, "4", null, "6");
    List<Integer> myInts = data.map(chain(substitute(null, "0"), Integer::new)).into(new ArrayList<Integer>());
    System.out.println(myInts);
    

    Would yield: [0, 0, 2, 0, 4, 0, 6]

    0 讨论(0)
  • 2020-12-25 14:58

    I am not aware of any library, however the code is just one line.

    Apart from Date, all boxed primitives have a String construtor, so this method does the trick:

    public static <I, O> O convert(I input, Class<O> outputClass) throws Exception {
        return input == null ? null : outputClass.getConstructor(String.class).newInstance(input.toString());
    }
    

    To cater for Dates, you could use instanceof within the method, but I would recommend a separate method, since converting dates is a format- and context-sensitive thing (eg String-->Date parses and uses which format?, Long-->Date sets the time).

    I have deliberately left error/special handling to the reader as an exercise.

    0 讨论(0)
  • 2020-12-25 14:58

    If you are using Spring Framework (spring-core), you can use class

    org.springframework.core.convert.support.DefaultConversionService
    

    Default constructor adds many types converter and you can add your own by implementing Converter interface and call addConverter(Converter). There is also nice unit test showing some conversion combinations.

    0 讨论(0)
  • 2020-12-25 15:00

    I found something by BalusC that looks close to what I'm asking for: http://balusc.blogspot.com/2007/08/generic-object-converter.html

    Unfortunately nothing involving Date conversion is supported, but as the comments indicate, more conversion methods are easily added. His class is essentially a nice little framework that uses reflection to gather up all conversion methods at runtime and put them in a HashMap<String, Method> where the key String is a unique id for that input-output combination.

    Still looking for other suggestions! Particularly for an API that would be more hands off than this code I linked to.

    0 讨论(0)
  • 2020-12-25 15:05

    Take a look at Variance, which allows you to set up a type conversion context with various converters registered and then move values into and out of a Variant type with type conversion handled by the context.

    Variant aVariant = Variant.of("1.2345");
    double aDouble = aVariant.doubleValue();
    
    int anInt = Variant.of("12").intValue();
    String aString = Variant.of(12.0).toString();
    Date aDate = Variant.of("2012-04-06").as(Date.class);
    String anIsoFormattedDate = Variant.of(aDate).in(isoDateFormattingContext).toString()
    

    Converters are just Guava Functions from one type to another, and you can register your own, overriding existing conversions where desired.

    0 讨论(0)
提交回复
热议问题