这个问题是对opensas的另一个问题的回应:在java中构建一个通用的初始化函数
从他的问题很明显,他需要从任何数据类型转换T1为另一种类型T2.当我说"数据类型"在这里,我的意思是类型仅限于那些常用来代表原始数据:Integer,String,Date等.对于这个问题,我们可以考虑原语装箱的目的.
我想知道是否有任何API支持类型之间的转换,其中输入和输出都被推广到一组受支持的数据类型.我看了一下Apache Commons的beanutils.converters包,但每个已知输入都有一个单独的转换器类.我正在寻找任何实现类似以下签名的功能:
static <IN, OUT> OUT convert(IN value, Class<OUT> targetType);
Run Code Online (Sandbox Code Playgroud)
要不然
static <IN, OUT> OUT convert(IN value, OUT defaultValue);
Run Code Online (Sandbox Code Playgroud)
实现这种映射本身并不太难,要么使用一堆else if指向各种Commons转换器的块,要么就是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
Run Code Online (Sandbox Code Playgroud)
更新:我链接的BalusC代码接近标记,Bohemian的答案是一个很好的轻量级解决方案(虽然它不适用于布尔转换).如果我们想要推广这些其他数据类型的转换,他也应该单独处理日期.我仍然希望得到更多的答案 - 特别是如果有更多的免提API可用于某处.
Boh*_*ian 21
我不知道任何库,但代码只是一行.
除了Date之外,所有盒装基元都有一个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());
}
Run Code Online (Sandbox Code Playgroud)
为了满足日期,你可以instanceof在方法中使用,但我会推荐一个单独的方法,因为转换日期是格式和上下文敏感的东西(例如String - > Date解析并使用哪种格式?,Long - >日期设定时间).
我故意将错误/特殊处理留给读者作为练习.
Edw*_*rzo 12
在JDK 8中,可以使用新java.util.functions.Mapper接口和lambda表达式轻松实现.
Mapper<String,Integer> atoi = s -> Integer.valueOf(s);
Integer r = atoi.map("10");
Run Code Online (Sandbox Code Playgroud)
使用方法引用它可以更简单:
Mapper<String, Integer> atoi = Integer::new;
Integer r = atoi.map("10");
Run Code Online (Sandbox Code Playgroud)
或者类似的事情:
List<Long> dates = asList(1344754620310L,1344754854877L);
List<Date> asDates = dates.map(Date::new).into(new ArrayList<Date>());
Run Code Online (Sandbox Code Playgroud)
或酷转换,如:
List<Integer> myInts = "5,4,3,2,1,0,6,7,8,9"
.splitAsStream(",")
.map(Integer::new)
.into(new ArrayList<Integer>());
Run Code Online (Sandbox Code Playgroud)
在目前实施的JDK8 API的,一些默认的映射器已被定义(即LongMapper,IntMapper,DoubleMapper),有一个叫实用工具类Mappers,它定义了一些其他类似的字符串映射器和身份映射,恒定映射器等.
我不确定这是否是你所追求的,但当然它必须是一个很好的实现方式.
像你建议的那样的案例:
static <IN, OUT> OUT convert(IN value, Class<OUT> targetType);
Run Code Online (Sandbox Code Playgroud)
可以使用Mappers实用程序类实现:
Mapper<String, Integer> atoi = Mappers.instantiate(String.class, Integer.class);
Integer r = atoi.map("10");
Run Code Online (Sandbox Code Playgroud)
而你的签名:
static <IN, OUT> OUT convert(IN value, OUT default);
Run Code Online (Sandbox Code Playgroud)
可以通过以下方式实现:
Mapper<String, Integer> atoi = chain(substitute(null, "0"), Integer::new);
Integer r = atoi.map(null); //produces 0
Run Code Online (Sandbox Code Playgroud)
就这样,像这样的代码......
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);
Run Code Online (Sandbox Code Playgroud)
会产量: [0, 0, 2, 0, 4, 0, 6]
| 归档时间: |
|
| 查看次数: |
25286 次 |
| 最近记录: |