全能类型转换器 - ConvertUtil
在我们日常开发工作中, 类型转换是跑不掉的,下面特别封装十分常用的方法
主要由下面几个部分组成:
1.转成数组
方法 | Description |
---|---|
toArray(T…) | 将动态数组转成数组. |
toArray(Collection<T>, Class<T>) | 将集合 collection 转成数组. |
toArray(String[], Class<T>) | 将字符串数组 toBeConvertedValue 转成指定类型 targetType 的数组. |
1.1 toArray(T…)
将动态数组转成数组.
示例:
String[] array = ConvertUtil.toArray("1", "2"); = ["1", "2"];
String[] emptyArray = ConvertUtil.<String>toArray(); = [] ; //= new String[] {};
Integer[] emptyArray = ConvertUtil.<Integer>toArray(); = [] ; //= new Integer[] {};
//注意
String[] nullArray = ConvertUtil.toArray(null) = null;
ConvertUtil.toArray((String) null) = new String[] { null }
注意:
- 数组是
具体化的(reified)
,而泛型在运行时是被擦除的(erasure)
。 数组是在运行时才去判断数组元素的类型约束,而泛型正好相反,在运行时,泛型的类型信息是会被擦除的,只有编译的时候才会对类型进行强化。泛型擦除的规则:
所有参数化容器类都被擦除成非参数化的(raw type); 如
List<E>
、List<List<E>>
都被擦除成 List- 所有参数化数组都被擦除成非参数化的数组;如
List<E>[]
,被擦除成 List[] - Raw type 的容器类,被擦除成其自身,如
List<E>
被擦 除成 List - 原生类型(int,String 还有 wrapper 类)都擦除成他们的自身
- 参数类型 E,如果没有上限,则被擦除成 Object
- 所有约束参数如
<? Extends E>、<X extends E>
都被擦 除成 E - 如果有多个约束,擦除成第一个,如
<T extends Object & E>
,则擦除成 Object 这将会导致下面的代码:
public static <K, V> Map<K, V[]> toArrayValueMap(Map<K, V> singleValueMap){
Map<K, V[]> arrayValueMap = newLinkedHashMap(singleValueMap.size());//保证顺序和参数singleValueMap顺序相同
for (Map.Entry<K, V> entry : singleValueMap.entrySet()){
arrayValueMap.put(entry.getKey(), toArray(entry.getValue()));//注意此处的Value不要声明成V,否则会变成Object数组
}
return arrayValueMap;
}
调用的时候,
Map<String, String> singleValueMap = MapUtil.newLinkedHashMap(2);
singleValueMap.put("province", "江苏省");
singleValueMap.put("city", "南通市");
Map<String, String[]> arrayValueMap = MapUtil.toArrayValueMap(singleValueMap);
String[] strings = arrayValueMap.get("province");//此时返回的是 Object[]
会出现异常
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
1.2 toArray(Collection<T>, Class<T>)
将集合 collection 转成数组.
示例:
List<String> list = new ArrayList<>();
list.add("xinge");
list.add("feilong");
以前你需要写成:
list.toArray(new String[list.size()]);
现在你只需要写成:
String[] array = ConvertUtil.toArray(list, String.class);
LOGGER.info(JsonUtil.format(array));
返回:
["xinge","feilong"]
1.3 toArray(String[], Class<T>)
将字符串数组 toBeConvertedValue 转成指定类型 targetType 的数组.
示例:
String[] ss = { "2", "1" };
toArray(ss, Long.class); = new Long[] { 2L, 1L }
ConvertUtil.toArray((String[]) null, Serializable.class) = null
2.转成List
方法 | Description |
---|---|
toList(T…) | 数组转成 (ArrayList). |
toList(Collection<T>) | 将 集合 collection 转成 list. |
toList(Enumeration<T>) | 将枚举 enumeration 转成 List. |
2.1 toList(T…)
数组转成 (ArrayList).
说明:
- 此方法返回的list可以进行add等操作
- 如果直接使用Arrays#asList(Object…)返回的list没有实现 Collection#add(Object)等方法,执行list.add("c");操作的话会导致异常!
- 而本方法使用 ArrayList.ArrayList(java.util.Collection) 来进行重新封装返回,可以执行正常的list操作特别适合:
如果你要通过以下方式来构造list:
List<String> list = new ArrayList<>();
list.add("feilong1");
list.add("feilong2");
list.add("feilong2");
list.add("feilong3");
此时你可以使用:
List<String> list = toList("feilong1", "feilong2", "feilong2", "feilong3");
代码会更简洁
甚至于:有很多时候,参数需要一个对象list,构造的时候,你需要这样
List<UserAddress> userAddresseList = new ArrayList<>();
UserAddress userAddress = new UserAddress();
userAddress.setAddress("上海");
userAddresseList.add(userAddress);
你可以重构成:
UserAddress userAddress = new UserAddress();
userAddress.setAddress("上海");
List<UserAddress> userAddresseList = toList(userAddress);
2.2 toList(Collection<T>)
将 集合 collection 转成 list.
说明:
- 此方法很适合快速的将set转成list这样的操作示例:
Set<String> set = new LinkedHashSet<>();
Collections.addAll(set, "a", "a", "b", "b");
LOGGER.debug("{}", toList(set));
返回:
[a,b]
2.3 toList(Enumeration<T>)
将枚举 enumeration 转成 List.
示例:
toList((Enumeration<String>) null) = emptyList()
3.转成Map
方法 | Description |
---|---|
toMap(K, V) | 将 key 和 value 直接转成map. |
toMap(K, V, K, V) | 将 key1 和 value1/key2 和 value2 直接转成map. |
toMap(Map<K, V>, Class<I>, Class<J>) | 将诸如 Map<String, String> 类型转成 Map<Integer, Integer> 类型. |
toMap(Map<K, V>, Transformer<K, I>, Transformer<V, J>) | 将诸如 Map<String, String> 类型转成 Map<Integer, Integer> 类型. |
toMap(Properties) | 将 properties 转换成map. |
toMap(Collection<E>) | 将 mapEntryCollection 转成map (LinkedHashMap). |
toMapUseEntrys(Entry<K, V>…) | 将 java.util.Map.Entry数组转成map (LinkedHashMap). |
3.1 toMap(K, V)
将 key 和 value 直接转成map.
说明:
- 返回是的是 LinkedHashMap
- 非常适合单key的场景,比如
Map<String, String> paramMap = new HashMap<>();
paramMap.put("name", "jinxin");
request.setParamMap(paramMap);
上面的3行代码可以重写成
request.setParamMap(toMap("name", "jinxin"));
一行代码就搞定了,很简洁,有木有~~
示例:
LOGGER.debug(JsonUtil.format(ConvertUtil.toMap("张飞", "丈八蛇矛")));
返回:
{"张飞": "丈八蛇矛"}
重构:对于以下代码:
private List<ShopCommand> loadShopCommandList(){
Map<String, Object> paraMap = new HashMap<>();
paraMap.put("orgTypeId", OrgType.ID_SHOP_TYPE);
return shopCommandDao.findShopListByOrgaTypeId(paraMap);
}
可以重构成:
private List<ShopCommand> loadShopCommandList(){
return shopCommandDao.findShopListByOrgaTypeId(ConvertUtil.toMap("orgTypeId", (Object) OrgType.ID_SHOP_TYPE));
}
3.2 toMap(K, V, K, V)
将 key1 和 value1/key2 和 value2 直接转成map.
说明:
- 返回是的是 LinkedHashMap
- 非常适合2个key的场景,比如
Map<String, String> paramMap = new HashMap<>();
paramMap.put("name", "jinxin");
paramMap.put("age", "18");
request.setParamMap(paramMap);
上面的3行代码可以重写成
request.setParamMap(toMap("name", "jinxin", "age", "18"));
一行代码就搞定了,很简洁,有木有~~
重构:对于以下代码:
Map<String, Long> map = new HashMap<>();
map.put("itemId", itemId);
map.put("memberId", memberId);
memberFavoritesDao.findMemberFavoritesByMemberIdAndItemId(map);
可以重构成:
Map<String, Long> map = ConvertUtil.toMap("itemId", itemId, "memberId", memberId);
memberFavoritesDao.findMemberFavoritesByMemberIdAndItemId(map);
3.3 toMap(Map<K, V>, Class<I>, Class<J>)
将诸如 Map<String, String> 类型转成 Map<Integer, Integer> 类型.
说明:
- 适合只是简单的将key value类型转换,而不需要自己再构建
Transformer
,再去调用toMap(Map, Transformer, Transformer)
,简化操作 - 返回的是 LinkedHashMap,顺序依照入参 inputMap
- 返回的是新的map,原来的toMap参数不受影响
- 也支持诸如
Map<String, Integer>
转Map<Integer, String>
(key和value 使用不同的转换器) - 也支持诸如
Map<String, String>
转Map<Integer, Integer[]>
(单值转数组) - 也支持诸如
Map<String[], String[]>
转Map<Integer[], Long[]>
(数组转数组)示例:**场景1:** 将Map<String, String>
转Map<Integer, Integer>
类型
Map<String, String> map = toMap("1", "2");
Map<Integer, Integer> returnMap = toMap(map, Integer.class, Integer.class);
// 输出测试
for (Map.Entry<Integer, Integer> entry : returnMap.entrySet()){
Integer key = entry.getKey();
Integer value = entry.getValue();
LOGGER.debug("key:[{}],value:[{}]", key, value);
}
返回:
key:[1],value:[2]
场景2: Map<String, String> 转 Map<Integer, Integer[]>
Map<String, String> map = toMap("1", "2,2");
//key和value转成不同的类型
Map<Integer, Integer[]> returnMap = toMap(map, Integer.class, Integer[].class);
// 输出测试
for (Map.Entry<Integer, Integer[]> entry : returnMap.entrySet()){
Integer key = entry.getKey();
Integer[] value = entry.getValue();
LOGGER.debug("key:[{}],value:[{}]", key, value);
}
返回:
key:[1],value:[[2, 2]]
场景3: Map<String[], String[]> 转 Map<Integer[], Long[]>
Map<String[], String[]> map = toMap(toArray("1"), toArray("2", "8"));
//key和value转成不同的类型
Map<Integer[], Long[]> returnMap = toMap(map, Integer[].class, Long[].class);
assertThat(returnMap, allOf(hasEntry(toArray(1), toArray(2L, 8L))));
3.4 toMap(Map<K, V>, Transformer<K, I>, Transformer<V, J>)
将诸如 Map<String, String> 类型转成 Map<Integer, Integer> 类型.
说明:
- 适合复杂的类型转换场景,如果只是简单的类型转换,你可以直接调用 toMap(Map, Class, Class)
- 返回的是 LinkedHashMap,顺序依照入参 inputMap
- 返回的是新的map,原来的toMap参数不受影响
- 也支持诸如 Map
转 Map (key和value 使用不同的转换器) - 也支持诸如 Map
转 Map (单值转数组) - 也支持诸如 Map
转 Map 示例:**场景1: **将Map<String, String> 转 Map<Integer, Integer> 类型(数组转数组)
Map<String, String> map = toMap("1", "2");
//key和value 都转成integer 使用相同的转换器
Transformer<String, Integer> transformer = new SimpleClassTransformer<>(Integer.class);
Map<Integer, Integer> returnMap = toMap(map, transformer, transformer);
// 输出测试
for (Map.Entry<Integer, Integer> entry : returnMap.entrySet()){
Integer key = entry.getKey();
Integer value = entry.getValue();
LOGGER.debug("key:[{}],value:[{}]", key, value);
}
返回:
key:[1],value:[2]
场景2: Map<String, String> 转 Map<Integer, Integer[]>
Map<String, String> map = toMap("1", "2,2");
Transformer<String, Integer> keyTransformer = new SimpleClassTransformer<>(Integer.class);
Transformer<String, Integer[]> valueTransformer = new SimpleClassTransformer<>(Integer[].class);
//key和value转成不同的类型
Map<Integer, Integer[]> returnMap = toMap(map, keyTransformer, valueTransformer);
// 输出测试
for (Map.Entry<Integer, Integer[]> entry : returnMap.entrySet()){
Integer key = entry.getKey();
Integer[] value = entry.getValue();
LOGGER.debug("key:[{}],value:[{}]", key, value);
}
返回:
key:[1],value:[[2, 2]]
场景3: Map<String[], String[]> 转 Map<Integer[], Long[]>
Map<String[], String[]> map = toMap(toArray("1"), toArray("2", "8"));
Transformer<String[], Integer[]> keyTransformer = new SimpleClassTransformer<>(Integer[].class);
Transformer<String[], Long[]> valueTransformer = new SimpleClassTransformer<>(Long[].class);
//key和value转成不同的类型
Map<Integer[], Long[]> returnMap = toMap(map, keyTransformer, valueTransformer);
assertThat(returnMap, allOf(hasEntry(toArray(1), toArray(2L, 8L))));
3.5 toMap(Properties)
将 properties 转换成map.
示例:
Properties properties = new Properties();
properties.setProperty("name", "feilong");
properties.setProperty("age", "18");
properties.setProperty("country", "china");
LOGGER.debug(JsonUtil.format(toMap(properties)));
返回:
{
"age": "18",
"country": "china",
"name": "feilong"
}
说明:
- 返回的map 经过了 SortUtil.sortMapByKeyAsc(Map)排序处理,方便输出日志
3.6 toMapUseEntrys(Entry<K, V>…)
将 java.util.Map.Entry数组转成map (LinkedHashMap).
说明:
- 返回是的是 LinkedHashMap,顺序依照参数 java.util.Map.Entry数组顺序,key是 java.util.Map.Entry.getKey(),value 是 java.util.Map.Entry.getValue()
- java.util.Map.Entry 已知实现类,你可以使用 Pair,或者 java.util.AbstractMap.SimpleEntry
Pair 示例:
Map<String, String> map = ConvertUtil.toMapUseEntrys(
Pair.of("张飞", "丈八蛇矛"),
Pair.of("关羽", "青龙偃月刀"),
Pair.of("赵云", "龙胆枪"),
Pair.of("刘备", "双股剑"));
LOGGER.debug(JsonUtil.format(map));
返回:
{
"张飞": "丈八蛇矛",
"关羽": "青龙偃月刀",
"赵云": "龙胆枪",
"刘备": "双股剑"
}
java.util.AbstractMap.SimpleEntry 示例:
Map<String, String> map = ConvertUtil.toMapUseEntrys(
new SimpleEntry<>("张飞", "丈八蛇矛"),
new SimpleEntry<>("关羽", "青龙偃月刀"),
new SimpleEntry<>("赵云", "龙胆枪"),
new SimpleEntry<>("刘备", "双股剑"));
LOGGER.debug(JsonUtil.format(map));
返回:
{
"张飞": "丈八蛇矛",
"关羽": "青龙偃月刀",
"赵云": "龙胆枪",
"刘备": "双股剑"
}
重构:以前初始化全局map的时候,你可能会这么写
// 除数和单位的map,必须是有顺序的 从大到小.
private static final Map<Long, String> DIVISOR_AND_UNIT_MAP = new LinkedHashMap<>();
static{
DIVISOR_AND_UNIT_MAP.put(FileUtils.ONE_TB, "TB");//(Terabyte,太字节,或百万兆字节)=1024GB,其中1024=2^10(2的10次方)
DIVISOR_AND_UNIT_MAP.put(FileUtils.ONE_GB, "GB");//(Gigabyte,吉字节,又称“千兆”)=1024MB
DIVISOR_AND_UNIT_MAP.put(FileUtils.ONE_MB, "MB");//(Megabyte,兆字节,简称“兆”)=1024KB
DIVISOR_AND_UNIT_MAP.put(FileUtils.ONE_KB, "KB");//(Kilobyte 千字节)=1024B
}
现在你可以重构成:
// 除数和单位的map,必须是有顺序的 从大到小.
private static final Map<Long, String> DIVISOR_AND_UNIT_MAP = ConvertUtil.toMapUseEntrys(
Pair.of(FileUtils.ONE_TB, "TB"), //(Terabyte,太字节,或百万兆字节)=1024GB,其中1024=2^10(2的10次方)
Pair.of(FileUtils.ONE_GB, "GB"), //(Gigabyte,吉字节,又称“千兆”)=1024MB
Pair.of(FileUtils.ONE_MB, "MB"), //(Megabyte,兆字节,简称“兆”)=1024KB
Pair.of(FileUtils.ONE_KB, "KB")); //(Kilobyte 千字节)=1024B
代码更加简洁
3.7 toMap(Collection<E>)
将 mapEntryCollection 转成map (LinkedHashMap).
说明:
- 返回是的是 LinkedHashMap,顺序依照参数 mapEntryCollection,key是
java.util.Map.Entry.getKey()
,value 是java.util.Map.Entry.getValue()
java.util.Map.Entry 已知实现类,你可以使用
Pair
,或者java.util.AbstractMap.SimpleEntry
Pair 示例:
Map<String, String> map = toMap(toList(//
Pair.of("张飞", "丈八蛇矛"),
Pair.of("关羽", "青龙偃月刀"),
Pair.of("赵云", "龙胆枪"),
Pair.of("刘备", "双股剑")));
LOGGER.debug(JsonUtil.format(map));
返回:
{
"张飞": "丈八蛇矛",
"关羽": "青龙偃月刀",
"赵云": "龙胆枪",
"刘备": "双股剑"
}
java.util.AbstractMap.SimpleEntry 示例:
Map<String, String> map = ConvertUtil.toMap(
toList(
new SimpleEntry<>("张飞", "丈八蛇矛"),
new SimpleEntry<>("关羽", "青龙偃月刀"),
new SimpleEntry<>("赵云", "龙胆枪"),
new SimpleEntry<>("刘备", "双股剑")));
LOGGER.debug(JsonUtil.format(map));
返回:
{
"张飞": "丈八蛇矛",
"关羽": "青龙偃月刀",
"赵云": "龙胆枪",
"刘备": "双股剑"
}
4.转成常用类型
方法 | Description |
---|---|
toInteger(Object) | 将 toBeConvertedValue 转换成 Integer类型. |
toInteger(Object, Integer) | 将 toBeConvertedValue 转换成 Integer类型,如果转换不了返回默认值 defaultValue. |
toIntegers(Object) | 将 toBeConvertedValue 转成Integer 数组. |
toBoolean(Object) | 将 toBeConvertedValue 转换成 Boolean类型. |
toLong(Object) | 将 toBeConvertedValue 转换成 Long类型. |
toLongs(Object) | 将 toBeConvertedValue 转成Long 数组. |
toBigDecimal(Object) | 将 toBeConvertedValue 转换成 java.math.BigDecimal. |
4.1 toInteger(Object)
将 toBeConvertedValue 转换成 Integer类型.
示例:
ConvertUtil.toInteger(null) = null
ConvertUtil.toInteger("aaaa") = null
ConvertUtil.toInteger(8L) = 8
ConvertUtil.toInteger("8") = 8
ConvertUtil.toInteger(new BigDecimal("8")) = 8
如果传入的参数 toBeConvertedValue
是 数组,那么取第一个元素进行转换,参见 AbstractConverter.convertArray(Object)
L227:
ConvertUtil.toInteger(new String[] { "1", "2", "3" }) = 1
如果传入的参数 toBeConvertedValue
是 集合,那么取第一个元素进行转换,参见 AbstractConverter.convertArray(Object)
Line234:
ConvertUtil.toInteger(toList("1", "2")) = 1
该方法非常适用 获取request请求的分页参数
示例:原来的写法:
public static Integer getCurrentPageNo(HttpServletRequest request,String pageParamName){
String pageNoString = RequestUtil.getParameter(request, pageParamName);
try{
int pageNo = Integer.parseInt(pageNoString);
return pageNo;
}catch (Exception e){
LOGGER.error(e.getClass().getName(), e);
}
return 1; // 不带这个参数或者转换异常返回1
}
现在可以更改成:
public static Integer getCurrentPageNo(HttpServletRequest request,String pageParamName){
String pageNoString = RequestUtil.getParameter(request, pageParamName);
Integer pageNo = ConvertUtil.toInteger(pageNoString);
return null == pageNo ? 1 : pageNo;
}
当然对于这种场景,最快捷的:调用支持默认值的 toInteger(Object, Integer)
方法
public static Integer getCurrentPageNo(HttpServletRequest request,String pageParamName){
String pageNoString = RequestUtil.getParameter(request, pageParamName);
return ConvertUtil.toInteger(pageNoString, 1);
}
4.2 toInteger(Object, Integer)
将 toBeConvertedValue 转换成 Integer类型,如果转换不了返回默认值 defaultValue.
示例:
ConvertUtil.toInteger(null,null) = null
ConvertUtil.toInteger(null,1) = 1
ConvertUtil.toInteger("aaaa",1) = 1
ConvertUtil.toInteger(8L,1) = 8
ConvertUtil.toInteger("8",1) = 8
ConvertUtil.toInteger(new BigDecimal("8"),1) = 8
如果传入的参数 toBeConvertedValue
是 数组,那么取第一个元素进行转换,参见 AbstractConverter.convertArray(Object)
L227:
ConvertUtil.toInteger(new String[] { "1", "2", "3" }, 8) = 1
如果传入的参数 toBeConvertedValue
是 集合,那么取第一个元素进行转换,参见 AbstractConverter.convertArray(Object)
Line234:
ConvertUtil.toInteger(toList("1", "2"), 8) = 1
该方法非常适用 获取request请求的分页参数
示例:原来的写法:
public static Integer getCurrentPageNo(HttpServletRequest request,String pageParamName){
String pageNoString = RequestUtil.getParameter(request, pageParamName);
try{
int pageNo = Integer.parseInt(pageNoString);
return pageNo;
}catch (Exception e){
LOGGER.error(e.getClass().getName(), e);
}
return 1; // 不带这个参数或者转换异常返回1
}
现在可以更改成:
public static Integer getCurrentPageNo(HttpServletRequest request,String pageParamName){
String pageNoString = RequestUtil.getParameter(request, pageParamName);
return ConvertUtil.toInteger(pageNoString, 1);
}
4.3 toIntegers(Object)
将 toBeConvertedValue
转成Integer 数组.
说明:
- 核心实现,参见
ArrayConverter.convertToType(Class, Object)
- 如果参数 toBeConvertedValue是 数组 或者 Collection ,参见ArrayConverter#convertToType(Class,Object),会构造一个Integer数组,长度就是 toBeConvertedValue的大小或者长度,然后迭代toBeConvertedValue依次逐个进行转换示例:
ConvertUtil.toIntegers(new String[] { "1", "2", "3" }) = [1,2,3]
ConvertUtil.toIntegers(toList("1", "2", "3")) = [1,2,3]
如果参数 toBeConvertedValue不是数组也不是Collection 那么首先会调用 ArrayConverter.convertToCollection(Class, Object) 将 toBeConvertedValue转成集合,转换逻辑参见 ArrayConverter.convertToCollection(Class, Object):
如果 toBeConvertedValue是Number, Boolean 或者 java.util.Date ,那么构造只有一个 toBeConvertedValue 元素的 List返回. 其他类型将转成字符串,然后调用 ArrayConverter.parseElements(Class, String)转成list. 具体转换逻辑为:
字符串期望是一个逗号分隔的字符串. 字符串可以被'{' 开头 和 '}'结尾的分隔符包裹,程序内部会自动截取. 会去除前后空白. Elements in the list may be delimited by single or double quotes. Within a quoted elements, the normal Java escape sequences are valid. 得到list之后,会构造一个Integer数组,长度就是 toBeConvertedValue的大小或者长度,然后迭代toBeConvertedValue依次逐个进行转换
示例:
ConvertUtil.toIntegers("1,2,3") = new Integer[] { 1, 2, 3 }
ConvertUtil.toIntegers("{1,2,3}") = new Integer[] { 1, 2, 3 }
ConvertUtil.toIntegers("{ 1 ,2,3}") = new Integer[] { 1, 2, 3 }
ConvertUtil.toIntegers("1,2, 3") = new Integer[] { 1, 2, 3 }
ConvertUtil.toIntegers("1,2 , 3") = new Integer[] { 1, 2, 3 }
每个元素转换成 Integer的时候,会调用 org.apache.commons.beanutils.converters.NumberConverter.convertToType(Class, Object),具体的规则是:
1.如果 元素是 Number类型 那么会调用 org.apache.commons.beanutils.converters.NumberConverter.toNumber(Class, Class, Number) 2.如果 元素是 Boolean类型 那么 true被转成1,false 转成 0 3.其他情况 将元素转成字符串,并trim,再进行转换 4.元素是null的情况 如果有元素是null,那么会调用 org.apache.commons.beanutils.converters.AbstractConverter.convert(Class, Object),会调用 org.apache.commons.beanutils.converters.AbstractConverter.handleMissing(Class) 方法,没有默认值的话,会抛出异常,然后catch之后返回 empty Integer 数组 示例:
ConvertUtil.toIntegers(toList("1", "2", " 3")) = new Integer[] { 1, 2, 3 }
ConvertUtil.toIntegers(toArray(true, false, false)) = new Integer[] { 1, 0, 0 }
ConvertUtil.toIntegers(new String[] { "1", null, "2", "3" })
4.4 toBoolean(Object)
将 toBeConvertedValue
转换成 Boolean类型.
示例:
ConvertUtil.toBoolean(null) = null
ConvertUtil.toBoolean(1L) = true
ConvertUtil.toBoolean("1") = true
ConvertUtil.toBoolean("9") = false
ConvertUtil.toBoolean("1,2,3") = false
逻辑及规则:
- 如果 "true", "yes", "y", "on", "1", 返回 true
- 如果 "false", "no", "n", "off", "0", 返回 false
- 其他抛出
conversionException
, 但是在 handleError(Class, Object, Throwable) 方法里面返回默认值, BooleanConverter 的默认值,参见 registerStandard(boolean, boolean) 你也可以调用
BooleanConverter(String[], String[], Object)
设置 trueStrings 和 falseStrings和 Boolean.parseBoolean(String)的区别:Boolean.parseBoolean(String)
,仅当(String != null)
并且String.equalsIgnoreCase("true")
返回 true
4.5 toLong(Object)
将 toBeConvertedValue
转换成 Long类型.
示例:
ConvertUtil.toLong(null) = null
ConvertUtil.toLong("aaaa") = null
ConvertUtil.toLong(8) = 8L
ConvertUtil.toLong("8") = 8L
ConvertUtil.toLong(new BigDecimal("8")) = 8L
如果传入的参数 toBeConvertedValue
是 数组,那么取第一个元素进行转换,参见 AbstractConverter.convertArray(Object)
L227:
ConvertUtil.toLong(new String[] { "1", "2", "3" }) = 1L
如果传入的参数 toBeConvertedValue
是 集合,那么取第一个元素进行转换,参见 AbstractConverter.convertArray(Object)
Line234:
ConvertUtil.toLong(toList("1", "2")) = 1L
4.6 toLongs(Object)
将 toBeConvertedValue 转成Long 数组.
说明:核心实现,参见 ArrayConverter.convertToType(Class, Object)
如果参数 toBeConvertedValue 是 数组 或者 Collection 参见ArrayConverter#convertToType(Class,Object)会构造一个Long数组,长度就是 toBeConvertedValue的大小或者长度,然后迭代toBeConvertedValue依次逐个进行转换
示例:
ConvertUtil.toLongs(new String[] { "1", "2", "3" } = [1L,2L,3L]
ConvertUtil.toLongs(toList("1", "2", "3")) = [1L,2L,3L]
如果参数 toBeConvertedValue不是数组也不是Collection 那么首先会调用 ArrayConverter.convertToCollection(Class, Object) 将 toBeConvertedValue转成集合,转换逻辑参见 ArrayConverter.convertToCollection(Class, Object):
如果 toBeConvertedValue是Number, Boolean 或者 java.util.Date ,那么构造只有一个 toBeConvertedValue 元素的 List返回. 其他类型将转成字符串,然后调用 ArrayConverter.parseElements(Class, String)转成list. 具体转换逻辑为:
字符串期望是一个逗号分隔的字符串. 字符串可以被'{' 开头 和 '}'结尾的分隔符包裹,程序内部会自动截取. 会去除前后空白. Elements in the list may be delimited by single or double quotes. Within a quoted elements, the normal Java escape sequences are valid. 得到list之后,会构造一个Long数组,长度就是 toBeConvertedValue的大小或者长度,然后迭代toBeConvertedValue依次逐个进行转换
示例:
ConvertUtil.toLongs("1,2,3") = new Long[] { 1L, 2L, 3L }
ConvertUtil.toLongs("{1,2,3}") = new Long[] { 1L, 2L, 3L }
ConvertUtil.toLongs("{ 1 ,2,3}") = new Long[] { 1L, 2L, 3L }
ConvertUtil.toLongs("1,2, 3") = new Long[] { 1L, 2L, 3L }
ConvertUtil.toLongs("1,2 , 3") = new Long[] { 1L, 2L, 3L }
每个元素转换成 Integer的时候,会调用 org.apache.commons.beanutils.converters.NumberConverter.convertToType(Class, Object),具体的规则是:
1.如果 元素是 Number类型 那么会调用 org.apache.commons.beanutils.converters.NumberConverter.toNumber(Class, Class, Number) 2.如果 元素是 Boolean类型 那么 true被转成1L,false 转成 0L 3.其他情况 将元素转成字符串,并trim,再进行转换 4.元素是null的情况 如果有元素是null,那么会调用 org.apache.commons.beanutils.converters.AbstractConverter.convert(Class, Object),会调用 org.apache.commons.beanutils.converters.AbstractConverter.handleMissing(Class) 方法,没有默认值的话,会抛出异常,然后catch之后返回 empty Integer 数组 示例:
ConvertUtil.toLongs(toList("1", "2", " 3")) = new Long[] { 1L, 2L, 3L }
ConvertUtil.toLongs(toArray(true, false, false)) = new Long[] { 1L, 0L, 0L }
ConvertUtil.toLongs(new String[] { "1", null, "2", "3" }) = new Long[] {}
特别适合以下形式的代码:
protected long[] getOrderIdLongs(String orderIds){
// 确认交易时候插入数据库的时候,不应该会出现空的情况
String[] orderIdArray = orderIds.split(",");
int orderLength = orderIdArray.length;
long[] ids = new long[orderLength];
for (int i = 0, j = orderLength; i < j; ++i){
ids[i] = Long.parseLong(orderIdArray[i]);
}
return ids;
}
可以重构成:
protected long[] getOrderIdLongs(String orderIds){
return toLongs(orderIds);
}
4.7 toBigDecimal(Object)
将 toBeConvertedValue 转换成 java.math.BigDecimal.
示例:
ConvertUtil.toBigDecimal(null) = null
ConvertUtil.toBigDecimal("aaaa") = null
ConvertUtil.toBigDecimal(8) = BigDecimal.valueOf(8)
ConvertUtil.toBigDecimal("8") = BigDecimal.valueOf(8)
ConvertUtil.toBigDecimal(new BigDecimal("8")) = BigDecimal.valueOf(8)
如果传入的参数 toBeConvertedValue 是 数组,那么取第一个元素进行转换,参见 AbstractConverter.convertArray(Object) L227:
ConvertUtil.toBigDecimal(new String[] { "1", "2", "3" }) = BigDecimal.valueOf(1)
如果传入的参数 toBeConvertedValue 是 集合,那么取第一个元素进行转换,参见 AbstractConverter.convertArray(Object) Line234:
ConvertUtil.toBigDecimal(toList("1", "2")) = BigDecimal.valueOf(1)
java.lang.Double 转成 java.math.BigDecimal注意点:
- 推荐使用
BigDecimal.valueOf(double)
,不建议使用new BigDecimal(double)
,参见 JDK APInew BigDecimal(0.1)
====> 0.1000000000000000055511151231257827021181583404541015625BigDecimal.valueOf(0.1)
====> 0.1
- 本方法底层调用的是
NumberConverter#toNumber(Class, Class, Number)
,正确的处理了 java.lang.Double 转成 java.math.BigDecimal
5.转成字符串
方法 | Description |
---|---|
toString(Object) | 把对象 toBeConvertedValue 转换成字符串. |
toString(Object[], ToStringConfig) | 将数组 arrays 通过ToStringConfig 拼接成字符串. |
toString(Collection<?>, ToStringConfig) | 将集合 collection 使用拼接配置 toStringConfig 拼接成字符串. |
5.1 toString(Object)
把对象 toBeConvertedValue
转换成字符串.
示例:
ConvertUtil.toString(1) = "1"
ConvertUtil.toString(toBigDecimal(1.0)) = "1.0"
ConvertUtil.toString(toLong(8L)) = "8"
注意:
- 该方法不适合 list转换成字符串,比如:
ConvertUtil.toString(toList("张飞", "关羽", "", "赵云")) = "张飞"
,请使用 toString(Collection, ToStringConfig)
该方法也不适合 array 转换成字符串,比如:
Integer[] int1 = { 2, null, 1, null };
LOGGER.debug(ConvertUtil.toString(int1)); = 2
请使用 toString(Object [], ToStringConfig)
对于 Array 转成 String:参见 ArrayConverter#convertToString(Object) 在转换的过程中,如果发现object是数组,将使用 Array#get(Object, int)来获得数据,如果发现不是数组,将会将object转成集合 ArrayConverter#convertToCollection(Class, Object)再转成迭代器 Collection.iterator()
在将object转成集合 ArrayConverter#convertToCollection(Class, Object)时候,有以下规则:
The string is expected to be a comma-separated list of values. 字符串可以被'{' and '}'分隔符包裹. 去除前后空白. Elements in the list may be delimited by single or double quotes. Within a quoted elements, the normal Java escape sequences are valid. 默认:
字段 | 说明 |
---|---|
int defaultSize | 指定构建的默认数组的大小 or if less than zero indicates that a null default value should be used. |
char delimiter = ',' | 分隔符,转成的string中的元素分隔符 |
char[] allowedChars = new char[] {'.', '-'} | 用于java.io.StreamTokenizer分隔字符串 |
boolean onlyFirstToString = true; | 只转第一个值 |
5.2 toString(Object[], ToStringConfig)
将数组 arrays 通过 ToStringConfig
拼接成字符串.
支持包装类型以及原始类型,比如 Integer [] arrays
或者 int []arrays
示例:
ConvertUtil.toString(toArray("a","b"),new ToStringConfig()) = "a,b"
ToStringConfig toStringConfig=new ToStringConfig(",");
toStringConfig.setIsJoinNullOrEmpty(false);
ConvertUtil.toString(toArray("a","b",null),new ToStringConfig()) = "a,b"
int[] ints = { 2, 1 };
ConvertUtil.toString(toArray(ints),new ToStringConfig()) = "2,1"
关于 default ToStringConfig:如果参数 toStringConfig 是null,则使用默认的规则:
- 连接符使用ToStringConfig.DEFAULT_CONNECTOR
- 拼接null或者empty元素
- 如果元素是null,使用StringUtils.EMPTY替代拼接
- 最后一个元素后面不拼接拼接符
5.3 toString(Collection<?>, ToStringConfig)
将集合 collection 使用拼接配置 toStringConfig 拼接成字符串.
示例:
List<String> list = new ArrayList<>();
list.add("feilong");
list.add("");
list.add("xinge");
ToStringConfig toStringConfig = new ToStringConfig(",");
toStringConfig.setIsJoinNullOrEmpty(false);
ConvertUtil.toString(list,toStringConfig);
输出:
feilong,xinge
你还可以使用这个方法来将集合换行输出,比如:
List<String> list = toList("飞龙", "小金", "四金", "金金金金");
ToStringConfig toStringConfig = new ToStringConfig(SystemUtils.LINE_SEPARATOR);
LOGGER.debug(ConvertUtil.toString(list, toStringConfig));
输出:
飞龙
小金
四金
金金金金
关于 default ToStringConfig:如果参数 toStringConfig 是null,则使用默认的规则:
- 连接符使用ToStringConfig.DEFAULT_CONNECTOR
- 拼接null或者empty元素
- 如果元素是null,使用StringUtils.EMPTY替代拼接
- 最后一个元素后面不拼接拼接符
6.转成字符串数组
方法 | Description |
---|---|
toStrings(Object) | 将 toBeConvertedValue 转成String数组. |
将 toBeConvertedValue
转成String数组.
说明:
- 该方法很适合将 非字符串数组的数组 转换成 字符串数组,比如
URL[] urls = {
URLUtil.newURL("http://www.exiaoshuo.com/jinyiyexing0/"),
URLUtil.newURL("http://www.exiaoshuo.com/jinyiyexing1/"),
URLUtil.newURL("http://www.exiaoshuo.com/jinyiyexing2/"),
null };
LOGGER.debug(JsonUtil.format(ConvertUtil.toStrings(urls)));
返回:
[
"http://www.exiaoshuo.com/jinyiyexing0/",
"http://www.exiaoshuo.com/jinyiyexing1/",
"http://www.exiaoshuo.com/jinyiyexing2/",
null
]
还有诸如 Integer[]
转成 String[]
ConvertUtil.toStrings(new Integer[] { 1, 2, 5 }) = [ "1", "2", "5" ]
也可以将字符串 解析成数组 in the Java language into a List individual Strings for each element, 根据以下规则:
- The string is expected to be a comma-separated list of values.
- 自动去除开头的 '{' 和 结束的'}'.
- 每个元素前后的空格将会去除.
- Elements in the list may be delimited by single or double quotes. Within a quoted elements, the normal Java escape sequences are valid.示例:
ConvertUtil.toStrings("{5,4, 8,2;8 9_5@3`a}"); = ["5","4","8","2","8","9","5","3","a"]
7.其他转换
方法 | Description |
---|---|
toEnumeration(Collection<T>) | 将集合 collection 转成Enumeration. |
toIterator(Object) | 将 toBeConvertedValue转成Iterator类型. |
toLocale(Object) | 将对象转成 Locale. |
toProperties(Map<String, String>) | 将map转成 Properties. |
convert(Object, Class<T>) | 将 toBeConvertedValue 转成指定 targetType 类型的对象. |
7.1 toEnumeration(Collection<T>)
将集合 collection
转成Enumeration.
说明:
- 一般情况,你可能不需要这个方法,不过在一些API的时候,需要Enumeration参数,此时调用这个方法来进行转换会比较方便示例:
ConvertUtil.toEnumeration(null) = Collections.emptyEnumeration()
7.2 toIterator(Object)
将 toBeConvertedValue
转成Iterator类型.
示例:
// null
toIterator(null) = null
//PrimitiveArray
int[] i2 = { 1, 2 };
Iterator<Integer> iterator = toIterator(i2);
//逗号分隔的字符串
Iterator<String> iterator = toIterator("1,2");
//collection
List<String> list = new ArrayList<>();
list.add("aaaa");
list.add("nnnnn");
Iterator<String> iterator = toIterator(list);
//Enumeration
Enumeration<Object> enumeration = new StringTokenizer("this is a test");
Iterator<String> iterator = toIterator(enumeration);
支持以下类型:
- 逗号分隔的字符串,先使用ConvertUtil.toStrings(Object) 转成数组
- 数组(包括 包装类型数组 以及 原始类型数组)
- 如果是java.util.Map,将 java.util.Map.values() 转成java.util.Iterator
- java.util.Collection
- java.util.Iterator
- java.util.Enumeration
- java.util.Dictionary
- org.w3c.dom.Node
- org.w3c.dom.NodeList
7.3 toLocale(Object)
将对象转成 Locale
.
示例:
ConvertUtil.toLocale(null) = null
ConvertUtil.toLocale("zh_CN") = Locale.CHINA
7.4 toProperties(Map<String, String>)
将map转成 Properties.
说明:
- 由于
Properties
只能保存非空的key和value,因此如果map 有key或者value是null,将会抛出NullPointerException
示例:
Map<String, String> map = toMap("name", "feilong");
Properties properties = ConvertUtil.toProperties(map);
LOGGER.debug(JsonUtil.format(properties));
返回:
{"name": "feilong"}
7.5 convert(Object, Class<T>)
将 toBeConvertedValue
转成指定 targetType
类型的对象.
示例:
ConvertUtil.convert("1", Integer.class) =1
ConvertUtil.convert("", Integer.class) =0
ConvertUtil.convert("1", Long.class) =1
此外,该方法特别适合数组类型的转换,比如 Type[] 转成 Class []:原来的写法:
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
int length = actualTypeArguments.length;
Class<?>[] klasses = new Class<?>[length];
for (int i = 0, j = length; i < j; ++i){
klasses[i] = (Class<?>) actualTypeArguments[i];
}
return klasses;
现在可以重构成:
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
return convert(actualTypeArguments, Class[].class);
注意:
- 如果targetType的转换器没有注册,那么传入的value原样返回, 比如ConvertUtil.convert("zh_CN", Locale.class) 由于找不到converter,那么返回"zh_CN".
- 如果转换不了,会使用默认值
如果传的
toBeConvertedValue
是toBeConvertedValue.getClass().isArray()
或者Collection
如果
targetType
不是数组 那么会取第一个元素进行转换, 参见AbstractConverter.convert(Class, Object),调用的 AbstractConverter.convertArray(Object) 方法如果
targetType
是数组 参见 ArrayConverter#convertToType(Class, Object) 会基于targetType 构造一个数组对象,大小长度就是 toBeConvertedValue的大小或者长度, 然后迭代 toBeConvertedValue 依次进行转换