2011-08-15 52 views
17

对这一问题的回答另一个问题由opensasbuilding a generic initializer function in java通用数据类型转换方法

从他的问题很明显,他需要从任何数据类型T1转换为另一种类型T2。当我在这里说“数据类型”时,我的意思是限于那些通常用于表示原始数据的类型:IntegerStringDate等。为了这个问题的目的,我们可以考虑原始数据被装箱。

我想知道是否有任何支持在输入和输出都推广到一组受支持的数据类型的类型之间进行转换的API。我看了一下Apache Commons' beanutils.converters package,但每个已知输入都有一个单独的转换器类。我在寻找实现类似以下签名的任何功能:

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

否则

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

这真的不会太难实现这种映射自己,无论是使用的一堆else if块指向各种Commons Converters,或者Map<Class<?>, Converter>出于同样的目的。但我想知道这种功能是否支持某个地方。

此外,如果这是一个重复,我很抱歉。我试着找到类似的问题,当我发现没有匹配这种情况时感到惊讶。

编辑:所以这段代码在行动中的一个例子是:

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:代码,我挂接近标准瀑布和波希米亚的回答是一个很好的轻量级解决方案的BalusC(尽管它不适用于布尔转换)。如果我们想推广这些其他数据类型的转换,那么日期应该分开处理也是正确的。尽管如此,我仍然希望获得额外的答案 - 尤其是如果有更多可用的无人值守API可用的话。

+0

你可以在操作中显示此代码吗?不能说我真的能明白你的目标是什么。 –

+0

@Maurício - 增加了一些例子 –

回答

11

JDK 8这可以很容易地用新的java.util.functions.Mapper接口和lambda expression实现。

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

使用方法引用它可以更简单:

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

或事物,如:

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

或冷却的转换,如:

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

在目前的实现的JDK8 API,af已经定义了新的默认映射器(即, LongMapperIntMapperDoubleMapper),并有一个名为Mappers实用工具类,它定义了一些其他类似的字符串映射器和身份映射,恒定映射等

我不知道这是否是你所追求的,但肯定它必须是一个很好的实现方法。

情况下,像你建议的一个:

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

可与Mappers实用类来实现:

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

和签名:

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

可以与实现例如:

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

因此,像这样的代码...

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); 

会产生:[0, 0, 2, 0, 4, 0, 6]

+1

+1好的答案 - 我认为我会接受Dominic's,直到JDK 8全面上市。 –

+5

现在是2016年,没有'java.util.functions.Mapper',但有'java.util.function.Function' – Alex

1

我发现BalusC东西看起来接近到什么要请我:http://balusc.blogspot.com/2007/08/generic-object-converter.html

遗憾的是没有涉及到日期的转换支持,但作为评论表明,很容易增加了更多的转换方法。他的课程基本上是一个很好的小框架,它使用反射来收集运行时的所有转换方法,并将它们放在HashMap<String, Method>中,其中密钥String是该输入输出组合的唯一ID。

还在寻找其他建议!特别是对于一个比我链接到的代码更接近实际的API。

18

我不知道任何库,但代码只是一行。

日期从

除此之外,所有盒装元都有一个String construtor,所以这种方法做的伎俩:

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

为迎合日期,你使用instanceof的方法中,但我会建议单独的方法,因为转换日期是格式和上下文敏感的东西(例如,字符串 - >日期分析和使用哪种格式?,长 - >日期设置时间)。

我故意将错误/特殊处理留给读者作为练习。

+1

+1这很酷,没有意识到所有盒装原语都有'String'构造函数。某些转换不受支持,例如'Boolean' =>'Integer',但这又是一个转折点。并且,正如你指出的那样,这不包括日期(或其他潜在的用户定义的“数据类型”) –

+3

另外:“我故意将错误/特殊处理留给读者作为练习。”我知道你只是想把它在一行:) –

+0

类型'我'在这里是不必要的;它可能只是'对象' – user102008

2

看看Variance,它允许您设置一个类型转换上下文与注册的各种转换器,然后将值移入和移出一个Variant类型,并通过上下文处理类型转换。

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() 

转换器只是GuavaFunctions从一种类型到另一种,你可以自己注册,覆盖在需要现有转换。

+0

+1很酷 - 感谢分享。 –

1

如果你正在使用Spring框架(弹簧芯),你可以使用类

org.springframework.core.convert.support.DefaultConversionService 

默认的构造函数添加多种类型的转换器,你可以添加你自己通过实现Converter接口并调用addConverter(Converter)。还有不错的unit test显示一些转换组合。