全能类型转换器 - ConvertUtil

在我们日常开发工作中, 类型转换是跑不掉的,下面特别封装十分常用的方法

主要由下面几个部分组成:

ConvertUtil

1.转成数组

方法Description
toArray(T…)将动态数组转成数组.
toArray(Collection<T>, Class<T>)将集合 collection 转成数组.
toArray(String[], Class<T>)将字符串数组 toBeConvertedValue 转成指定类型 targetType 的数组.

1.1 toArray(T…)

将动态数组转成数组.

示例:

  1. String[] array = ConvertUtil.toArray("1", "2"); = ["1", "2"];
  2. String[] emptyArray = ConvertUtil.<String>toArray(); = [] ; //= new String[] {};
  3. Integer[] emptyArray = ConvertUtil.<Integer>toArray(); = [] ; //= new Integer[] {};
  4. //注意
  5. String[] nullArray = ConvertUtil.toArray(null) = null;
  6. 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 这将会导致下面的代码:
  1. public static <K, V> Map<K, V[]> toArrayValueMap(Map<K, V> singleValueMap){
  2. Map<K, V[]> arrayValueMap = newLinkedHashMap(singleValueMap.size());//保证顺序和参数singleValueMap顺序相同
  3. for (Map.Entry<K, V> entry : singleValueMap.entrySet()){
  4. arrayValueMap.put(entry.getKey(), toArray(entry.getValue()));//注意此处的Value不要声明成V,否则会变成Object数组
  5. }
  6. return arrayValueMap;
  7. }

调用的时候,

  1. Map<String, String> singleValueMap = MapUtil.newLinkedHashMap(2);
  2. singleValueMap.put("province", "江苏省");
  3. singleValueMap.put("city", "南通市");
  4. Map<String, String[]> arrayValueMap = MapUtil.toArrayValueMap(singleValueMap);
  5. String[] strings = arrayValueMap.get("province");//此时返回的是 Object[]

会出现异常

  1. java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;

1.2 toArray(Collection<T>, Class<T>)

将集合 collection 转成数组.

示例:

  1. List<String> list = new ArrayList<>();
  2. list.add("xinge");
  3. list.add("feilong");

以前你需要写成:

  1. list.toArray(new String[list.size()]);

现在你只需要写成:

  1. String[] array = ConvertUtil.toArray(list, String.class);
  2. LOGGER.info(JsonUtil.format(array));

返回:

  1. ["xinge","feilong"]

1.3 toArray(String[], Class<T>)

将字符串数组 toBeConvertedValue 转成指定类型 targetType 的数组.

示例:

  1. String[] ss = { "2", "1" };
  2. toArray(ss, Long.class); = new Long[] { 2L, 1L }
  3. 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:

  1. List<String> list = new ArrayList<>();
  2. list.add("feilong1");
  3. list.add("feilong2");
  4. list.add("feilong2");
  5. list.add("feilong3");

此时你可以使用:

  1. List<String> list = toList("feilong1", "feilong2", "feilong2", "feilong3");

代码会更简洁

甚至于:有很多时候,参数需要一个对象list,构造的时候,你需要这样

  1. List<UserAddress> userAddresseList = new ArrayList<>();
  2. UserAddress userAddress = new UserAddress();
  3. userAddress.setAddress("上海");
  4. userAddresseList.add(userAddress);

你可以重构成:

  1. UserAddress userAddress = new UserAddress();
  2. userAddress.setAddress("上海");
  3. List<UserAddress> userAddresseList = toList(userAddress);

2.2 toList(Collection<T>)

将 集合 collection 转成 list.

说明:

  • 此方法很适合快速的将set转成list这样的操作示例:
  1. Set<String> set = new LinkedHashSet<>();
  2. Collections.addAll(set, "a", "a", "b", "b");
  3. LOGGER.debug("{}", toList(set));

返回:

  1. [a,b]

2.3 toList(Enumeration<T>)

将枚举 enumeration 转成 List.

示例:

  1. 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的场景,比如
  1. Map<String, String> paramMap = new HashMap<>();
  2. paramMap.put("name", "jinxin");
  3. request.setParamMap(paramMap);

上面的3行代码可以重写成

  1. request.setParamMap(toMap("name", "jinxin"));

一行代码就搞定了,很简洁,有木有~~

示例:

  1. LOGGER.debug(JsonUtil.format(ConvertUtil.toMap("张飞", "丈八蛇矛")));

返回:

  1. {"张飞": "丈八蛇矛"}

重构:对于以下代码:

  1. private List<ShopCommand> loadShopCommandList(){
  2. Map<String, Object> paraMap = new HashMap<>();
  3. paraMap.put("orgTypeId", OrgType.ID_SHOP_TYPE);
  4. return shopCommandDao.findShopListByOrgaTypeId(paraMap);
  5. }

可以重构成:

  1. private List<ShopCommand> loadShopCommandList(){
  2. return shopCommandDao.findShopListByOrgaTypeId(ConvertUtil.toMap("orgTypeId", (Object) OrgType.ID_SHOP_TYPE));
  3. }

3.2 toMap(K, V, K, V)

将 key1 和 value1/key2 和 value2 直接转成map.

说明:

  • 返回是的是 LinkedHashMap
  • 非常适合2个key的场景,比如
  1. Map<String, String> paramMap = new HashMap<>();
  2. paramMap.put("name", "jinxin");
  3. paramMap.put("age", "18");
  4. request.setParamMap(paramMap);

上面的3行代码可以重写成

  1. request.setParamMap(toMap("name", "jinxin", "age", "18"));

一行代码就搞定了,很简洁,有木有~~

重构:对于以下代码:

  1. Map<String, Long> map = new HashMap<>();
  2. map.put("itemId", itemId);
  3. map.put("memberId", memberId);
  4. memberFavoritesDao.findMemberFavoritesByMemberIdAndItemId(map);

可以重构成:

  1. Map<String, Long> map = ConvertUtil.toMap("itemId", itemId, "memberId", memberId);
  2. 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> 类型
  1. Map<String, String> map = toMap("1", "2");
  2. Map<Integer, Integer> returnMap = toMap(map, Integer.class, Integer.class);
  3. // 输出测试
  4. for (Map.Entry<Integer, Integer> entry : returnMap.entrySet()){
  5. Integer key = entry.getKey();
  6. Integer value = entry.getValue();
  7. LOGGER.debug("key:[{}],value:[{}]", key, value);
  8. }

返回:

  1. key:[1],value:[2]

场景2: Map<String, String> 转 Map<Integer, Integer[]>

  1. Map<String, String> map = toMap("1", "2,2");
  2. //key和value转成不同的类型
  3. Map<Integer, Integer[]> returnMap = toMap(map, Integer.class, Integer[].class);
  4. // 输出测试
  5. for (Map.Entry<Integer, Integer[]> entry : returnMap.entrySet()){
  6. Integer key = entry.getKey();
  7. Integer[] value = entry.getValue();
  8. LOGGER.debug("key:[{}],value:[{}]", key, value);
  9. }

返回:

  1. key:[1],value:[[2, 2]]

场景3: Map<String[], String[]> 转 Map<Integer[], Long[]>

  1. Map<String[], String[]> map = toMap(toArray("1"), toArray("2", "8"));
  2. //key和value转成不同的类型
  3. Map<Integer[], Long[]> returnMap = toMap(map, Integer[].class, Long[].class);
  4. 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> 类型
  1. Map<String, String> map = toMap("1", "2");
  2. //key和value 都转成integer 使用相同的转换器
  3. Transformer<String, Integer> transformer = new SimpleClassTransformer<>(Integer.class);
  4. Map<Integer, Integer> returnMap = toMap(map, transformer, transformer);
  5. // 输出测试
  6. for (Map.Entry<Integer, Integer> entry : returnMap.entrySet()){
  7. Integer key = entry.getKey();
  8. Integer value = entry.getValue();
  9. LOGGER.debug("key:[{}],value:[{}]", key, value);
  10. }

返回:

  1. key:[1],value:[2]

场景2: Map<String, String> 转 Map<Integer, Integer[]>

  1. Map<String, String> map = toMap("1", "2,2");
  2. Transformer<String, Integer> keyTransformer = new SimpleClassTransformer<>(Integer.class);
  3. Transformer<String, Integer[]> valueTransformer = new SimpleClassTransformer<>(Integer[].class);
  4. //key和value转成不同的类型
  5. Map<Integer, Integer[]> returnMap = toMap(map, keyTransformer, valueTransformer);
  6. // 输出测试
  7. for (Map.Entry<Integer, Integer[]> entry : returnMap.entrySet()){
  8. Integer key = entry.getKey();
  9. Integer[] value = entry.getValue();
  10. LOGGER.debug("key:[{}],value:[{}]", key, value);
  11. }

返回:

  1. key:[1],value:[[2, 2]]

场景3: Map<String[], String[]> 转 Map<Integer[], Long[]>

  1. Map<String[], String[]> map = toMap(toArray("1"), toArray("2", "8"));
  2. Transformer<String[], Integer[]> keyTransformer = new SimpleClassTransformer<>(Integer[].class);
  3. Transformer<String[], Long[]> valueTransformer = new SimpleClassTransformer<>(Long[].class);
  4. //key和value转成不同的类型
  5. Map<Integer[], Long[]> returnMap = toMap(map, keyTransformer, valueTransformer);
  6. assertThat(returnMap, allOf(hasEntry(toArray(1), toArray(2L, 8L))));

3.5 toMap(Properties)

将 properties 转换成map.

示例:

  1. Properties properties = new Properties();
  2. properties.setProperty("name", "feilong");
  3. properties.setProperty("age", "18");
  4. properties.setProperty("country", "china");
  5. LOGGER.debug(JsonUtil.format(toMap(properties)));

返回:

  1. {
  2. "age": "18",
  3. "country": "china",
  4. "name": "feilong"
  5. }

说明:

  • 返回的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 示例:

  1. Map<String, String> map = ConvertUtil.toMapUseEntrys(
  2. Pair.of("张飞", "丈八蛇矛"),
  3. Pair.of("关羽", "青龙偃月刀"),
  4. Pair.of("赵云", "龙胆枪"),
  5. Pair.of("刘备", "双股剑"));
  6. LOGGER.debug(JsonUtil.format(map));

返回:

  1. {
  2. "张飞": "丈八蛇矛",
  3. "关羽": "青龙偃月刀",
  4. "赵云": "龙胆枪",
  5. "刘备": "双股剑"
  6. }

java.util.AbstractMap.SimpleEntry 示例:

  1. Map<String, String> map = ConvertUtil.toMapUseEntrys(
  2. new SimpleEntry<>("张飞", "丈八蛇矛"),
  3. new SimpleEntry<>("关羽", "青龙偃月刀"),
  4. new SimpleEntry<>("赵云", "龙胆枪"),
  5. new SimpleEntry<>("刘备", "双股剑"));
  6. LOGGER.debug(JsonUtil.format(map));

返回:

  1. {
  2. "张飞": "丈八蛇矛",
  3. "关羽": "青龙偃月刀",
  4. "赵云": "龙胆枪",
  5. "刘备": "双股剑"
  6. }

重构:以前初始化全局map的时候,你可能会这么写

  1. // 除数和单位的map,必须是有顺序的 从大到小.
  2. private static final Map<Long, String> DIVISOR_AND_UNIT_MAP = new LinkedHashMap<>();
  3. static{
  4. DIVISOR_AND_UNIT_MAP.put(FileUtils.ONE_TB, "TB");//(Terabyte,太字节,或百万兆字节)=1024GB,其中1024=2^10(2的10次方)
  5. DIVISOR_AND_UNIT_MAP.put(FileUtils.ONE_GB, "GB");//(Gigabyte,吉字节,又称“千兆”)=1024MB
  6. DIVISOR_AND_UNIT_MAP.put(FileUtils.ONE_MB, "MB");//(Megabyte,兆字节,简称“兆”)=1024KB
  7. DIVISOR_AND_UNIT_MAP.put(FileUtils.ONE_KB, "KB");//(Kilobyte 千字节)=1024B
  8. }

现在你可以重构成:

  1. // 除数和单位的map,必须是有顺序的 从大到小.
  2. private static final Map<Long, String> DIVISOR_AND_UNIT_MAP = ConvertUtil.toMapUseEntrys(
  3. Pair.of(FileUtils.ONE_TB, "TB"), //(Terabyte,太字节,或百万兆字节)=1024GB,其中1024=2^10(2的10次方)
  4. Pair.of(FileUtils.ONE_GB, "GB"), //(Gigabyte,吉字节,又称“千兆”)=1024MB
  5. Pair.of(FileUtils.ONE_MB, "MB"), //(Megabyte,兆字节,简称“兆”)=1024KB
  6. 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 示例:

  1. Map<String, String> map = toMap(toList(//
  2. Pair.of("张飞", "丈八蛇矛"),
  3. Pair.of("关羽", "青龙偃月刀"),
  4. Pair.of("赵云", "龙胆枪"),
  5. Pair.of("刘备", "双股剑")));
  6. LOGGER.debug(JsonUtil.format(map));

返回:

  1. {
  2. "张飞": "丈八蛇矛",
  3. "关羽": "青龙偃月刀",
  4. "赵云": "龙胆枪",
  5. "刘备": "双股剑"
  6. }

java.util.AbstractMap.SimpleEntry 示例:

  1. Map<String, String> map = ConvertUtil.toMap(
  2. toList(
  3. new SimpleEntry<>("张飞", "丈八蛇矛"),
  4. new SimpleEntry<>("关羽", "青龙偃月刀"),
  5. new SimpleEntry<>("赵云", "龙胆枪"),
  6. new SimpleEntry<>("刘备", "双股剑")));
  7. LOGGER.debug(JsonUtil.format(map));

返回:

  1. {
  2. "张飞": "丈八蛇矛",
  3. "关羽": "青龙偃月刀",
  4. "赵云": "龙胆枪",
  5. "刘备": "双股剑"
  6. }

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类型.

示例:

  1. ConvertUtil.toInteger(null) = null
  2. ConvertUtil.toInteger("aaaa") = null
  3. ConvertUtil.toInteger(8L) = 8
  4. ConvertUtil.toInteger("8") = 8
  5. ConvertUtil.toInteger(new BigDecimal("8")) = 8

如果传入的参数 toBeConvertedValue 是 数组,那么取第一个元素进行转换,参见 AbstractConverter.convertArray(Object) L227:

  1. ConvertUtil.toInteger(new String[] { "1", "2", "3" }) = 1

如果传入的参数 toBeConvertedValue 是 集合,那么取第一个元素进行转换,参见 AbstractConverter.convertArray(Object) Line234:

  1. ConvertUtil.toInteger(toList("1", "2")) = 1

该方法非常适用 获取request请求的分页参数

示例:原来的写法:

  1. public static Integer getCurrentPageNo(HttpServletRequest request,String pageParamName){
  2. String pageNoString = RequestUtil.getParameter(request, pageParamName);
  3. try{
  4. int pageNo = Integer.parseInt(pageNoString);
  5. return pageNo;
  6. }catch (Exception e){
  7. LOGGER.error(e.getClass().getName(), e);
  8. }
  9. return 1; // 不带这个参数或者转换异常返回1
  10. }

现在可以更改成:

  1. public static Integer getCurrentPageNo(HttpServletRequest request,String pageParamName){
  2. String pageNoString = RequestUtil.getParameter(request, pageParamName);
  3. Integer pageNo = ConvertUtil.toInteger(pageNoString);
  4. return null == pageNo ? 1 : pageNo;
  5. }

当然对于这种场景,最快捷的:调用支持默认值的 toInteger(Object, Integer) 方法

  1. public static Integer getCurrentPageNo(HttpServletRequest request,String pageParamName){
  2. String pageNoString = RequestUtil.getParameter(request, pageParamName);
  3. return ConvertUtil.toInteger(pageNoString, 1);
  4. }

4.2 toInteger(Object, Integer)

将 toBeConvertedValue 转换成 Integer类型,如果转换不了返回默认值 defaultValue.

示例:

  1. ConvertUtil.toInteger(null,null) = null
  2. ConvertUtil.toInteger(null,1) = 1
  3. ConvertUtil.toInteger("aaaa",1) = 1
  4. ConvertUtil.toInteger(8L,1) = 8
  5. ConvertUtil.toInteger("8",1) = 8
  6. ConvertUtil.toInteger(new BigDecimal("8"),1) = 8

如果传入的参数 toBeConvertedValue 是 数组,那么取第一个元素进行转换,参见 AbstractConverter.convertArray(Object) L227:

  1. ConvertUtil.toInteger(new String[] { "1", "2", "3" }, 8) = 1

如果传入的参数 toBeConvertedValue 是 集合,那么取第一个元素进行转换,参见 AbstractConverter.convertArray(Object) Line234:

  1. ConvertUtil.toInteger(toList("1", "2"), 8) = 1

该方法非常适用 获取request请求的分页参数

示例:原来的写法:

  1. public static Integer getCurrentPageNo(HttpServletRequest request,String pageParamName){
  2. String pageNoString = RequestUtil.getParameter(request, pageParamName);
  3. try{
  4. int pageNo = Integer.parseInt(pageNoString);
  5. return pageNo;
  6. }catch (Exception e){
  7. LOGGER.error(e.getClass().getName(), e);
  8. }
  9. return 1; // 不带这个参数或者转换异常返回1
  10. }

现在可以更改成:

  1. public static Integer getCurrentPageNo(HttpServletRequest request,String pageParamName){
  2. String pageNoString = RequestUtil.getParameter(request, pageParamName);
  3. return ConvertUtil.toInteger(pageNoString, 1);
  4. }

4.3 toIntegers(Object)

toBeConvertedValue 转成Integer 数组.

说明:

  • 核心实现,参见 ArrayConverter.convertToType(Class, Object)
  • 如果参数 toBeConvertedValue是 数组 或者 Collection ,参见ArrayConverter#convertToType(Class,Object),会构造一个Integer数组,长度就是 toBeConvertedValue的大小或者长度,然后迭代toBeConvertedValue依次逐个进行转换示例:
  1. ConvertUtil.toIntegers(new String[] { "1", "2", "3" }) = [1,2,3]
  2. 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依次逐个进行转换

示例:

  1. ConvertUtil.toIntegers("1,2,3") = new Integer[] { 1, 2, 3 }
  2. ConvertUtil.toIntegers("{1,2,3}") = new Integer[] { 1, 2, 3 }
  3. ConvertUtil.toIntegers("{ 1 ,2,3}") = new Integer[] { 1, 2, 3 }
  4. ConvertUtil.toIntegers("1,2, 3") = new Integer[] { 1, 2, 3 }
  5. 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 数组 示例:

  1. ConvertUtil.toIntegers(toList("1", "2", " 3")) = new Integer[] { 1, 2, 3 }
  2. ConvertUtil.toIntegers(toArray(true, false, false)) = new Integer[] { 1, 0, 0 }
  3. ConvertUtil.toIntegers(new String[] { "1", null, "2", "3" })

4.4 toBoolean(Object)

toBeConvertedValue 转换成 Boolean类型.

示例:

  1. ConvertUtil.toBoolean(null) = null
  2. ConvertUtil.toBoolean(1L) = true
  3. ConvertUtil.toBoolean("1") = true
  4. ConvertUtil.toBoolean("9") = false
  5. 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类型.

示例:

  1. ConvertUtil.toLong(null) = null
  2. ConvertUtil.toLong("aaaa") = null
  3. ConvertUtil.toLong(8) = 8L
  4. ConvertUtil.toLong("8") = 8L
  5. ConvertUtil.toLong(new BigDecimal("8")) = 8L

如果传入的参数 toBeConvertedValue 是 数组,那么取第一个元素进行转换,参见 AbstractConverter.convertArray(Object) L227:

  1. ConvertUtil.toLong(new String[] { "1", "2", "3" }) = 1L

如果传入的参数 toBeConvertedValue 是 集合,那么取第一个元素进行转换,参见 AbstractConverter.convertArray(Object) Line234:

  1. 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依次逐个进行转换

示例:

  1. ConvertUtil.toLongs(new String[] { "1", "2", "3" } = [1L,2L,3L]
  2. 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依次逐个进行转换

示例:

  1. ConvertUtil.toLongs("1,2,3") = new Long[] { 1L, 2L, 3L }
  2. ConvertUtil.toLongs("{1,2,3}") = new Long[] { 1L, 2L, 3L }
  3. ConvertUtil.toLongs("{ 1 ,2,3}") = new Long[] { 1L, 2L, 3L }
  4. ConvertUtil.toLongs("1,2, 3") = new Long[] { 1L, 2L, 3L }
  5. 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 数组 示例:

  1. ConvertUtil.toLongs(toList("1", "2", " 3")) = new Long[] { 1L, 2L, 3L }
  2. ConvertUtil.toLongs(toArray(true, false, false)) = new Long[] { 1L, 0L, 0L }
  3. ConvertUtil.toLongs(new String[] { "1", null, "2", "3" }) = new Long[] {}

特别适合以下形式的代码:

  1. protected long[] getOrderIdLongs(String orderIds){
  2. // 确认交易时候插入数据库的时候,不应该会出现空的情况
  3. String[] orderIdArray = orderIds.split(",");
  4. int orderLength = orderIdArray.length;
  5. long[] ids = new long[orderLength];
  6. for (int i = 0, j = orderLength; i < j; ++i){
  7. ids[i] = Long.parseLong(orderIdArray[i]);
  8. }
  9. return ids;
  10. }

可以重构成:

  1. protected long[] getOrderIdLongs(String orderIds){
  2. return toLongs(orderIds);
  3. }

4.7 toBigDecimal(Object)

将 toBeConvertedValue 转换成 java.math.BigDecimal.

示例:

  1. ConvertUtil.toBigDecimal(null) = null
  2. ConvertUtil.toBigDecimal("aaaa") = null
  3. ConvertUtil.toBigDecimal(8) = BigDecimal.valueOf(8)
  4. ConvertUtil.toBigDecimal("8") = BigDecimal.valueOf(8)
  5. ConvertUtil.toBigDecimal(new BigDecimal("8")) = BigDecimal.valueOf(8)

如果传入的参数 toBeConvertedValue 是 数组,那么取第一个元素进行转换,参见 AbstractConverter.convertArray(Object) L227:

  1. ConvertUtil.toBigDecimal(new String[] { "1", "2", "3" }) = BigDecimal.valueOf(1)

如果传入的参数 toBeConvertedValue 是 集合,那么取第一个元素进行转换,参见 AbstractConverter.convertArray(Object) Line234:

  1. ConvertUtil.toBigDecimal(toList("1", "2")) = BigDecimal.valueOf(1)

java.lang.Double 转成 java.math.BigDecimal注意点:

  • 推荐使用 BigDecimal.valueOf(double),不建议使用 new BigDecimal(double),参见 JDK API
    • new BigDecimal(0.1) ====> 0.1000000000000000055511151231257827021181583404541015625
    • BigDecimal.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 转换成字符串.

示例:

  1. ConvertUtil.toString(1) = "1"
  2. ConvertUtil.toString(toBigDecimal(1.0)) = "1.0"
  3. ConvertUtil.toString(toLong(8L)) = "8"

注意:

  • 该方法不适合 list转换成字符串,比如:
  1. ConvertUtil.toString(toList("张飞", "关羽", "", "赵云")) = "张飞"

,请使用 toString(Collection, ToStringConfig)


该方法也不适合 array 转换成字符串,比如:

  1. Integer[] int1 = { 2, null, 1, null };
  2. 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

示例:

  1. ConvertUtil.toString(toArray("a","b"),new ToStringConfig()) = "a,b"
  2. ToStringConfig toStringConfig=new ToStringConfig(",");
  3. toStringConfig.setIsJoinNullOrEmpty(false);
  4. ConvertUtil.toString(toArray("a","b",null),new ToStringConfig()) = "a,b"
  5. int[] ints = { 2, 1 };
  6. 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 拼接成字符串.

示例:

  1. List<String> list = new ArrayList<>();
  2. list.add("feilong");
  3. list.add("");
  4. list.add("xinge");
  5. ToStringConfig toStringConfig = new ToStringConfig(",");
  6. toStringConfig.setIsJoinNullOrEmpty(false);
  7. ConvertUtil.toString(list,toStringConfig);

输出:

  1. feilong,xinge

你还可以使用这个方法来将集合换行输出,比如:

  1. List<String> list = toList("飞龙", "小金", "四金", "金金金金");
  2. ToStringConfig toStringConfig = new ToStringConfig(SystemUtils.LINE_SEPARATOR);
  3. LOGGER.debug(ConvertUtil.toString(list, toStringConfig));

输出:

  1. 飞龙
  2. 小金
  3. 四金
  4. 金金金金

关于 default ToStringConfig:如果参数 toStringConfig 是null,则使用默认的规则:

  • 连接符使用ToStringConfig.DEFAULT_CONNECTOR
  • 拼接null或者empty元素
  • 如果元素是null,使用StringUtils.EMPTY替代拼接
  • 最后一个元素后面不拼接拼接符

6.转成字符串数组

方法Description
toStrings(Object)将 toBeConvertedValue 转成String数组.

toBeConvertedValue 转成String数组.

说明:

  • 该方法很适合将 非字符串数组的数组 转换成 字符串数组,比如
  1. URL[] urls = {
  2. URLUtil.newURL("http://www.exiaoshuo.com/jinyiyexing0/"),
  3. URLUtil.newURL("http://www.exiaoshuo.com/jinyiyexing1/"),
  4. URLUtil.newURL("http://www.exiaoshuo.com/jinyiyexing2/"),
  5. null };
  6. LOGGER.debug(JsonUtil.format(ConvertUtil.toStrings(urls)));

返回:

  1. [
  2. "http://www.exiaoshuo.com/jinyiyexing0/",
  3. "http://www.exiaoshuo.com/jinyiyexing1/",
  4. "http://www.exiaoshuo.com/jinyiyexing2/",
  5. null
  6. ]

还有诸如 Integer[]转成 String[]

  1. 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.示例:
  1. 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参数,此时调用这个方法来进行转换会比较方便示例:
  1. ConvertUtil.toEnumeration(null) = Collections.emptyEnumeration()

7.2 toIterator(Object)

toBeConvertedValue 转成Iterator类型.

示例:

  1. // null
  2. toIterator(null) = null
  3. //PrimitiveArray
  4. int[] i2 = { 1, 2 };
  5. Iterator<Integer> iterator = toIterator(i2);
  6. //逗号分隔的字符串
  7. Iterator<String> iterator = toIterator("1,2");
  8. //collection
  9. List<String> list = new ArrayList<>();
  10. list.add("aaaa");
  11. list.add("nnnnn");
  12. Iterator<String> iterator = toIterator(list);
  13. //Enumeration
  14. Enumeration<Object> enumeration = new StringTokenizer("this is a test");
  15. 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.

示例:

  1. ConvertUtil.toLocale(null) = null
  2. ConvertUtil.toLocale("zh_CN") = Locale.CHINA

7.4 toProperties(Map<String, String>)

将map转成 Properties.

说明:

  • 由于 Properties 只能保存非空的key和value,因此如果map 有key或者value是null,将会抛出 NullPointerException示例:
  1. Map<String, String> map = toMap("name", "feilong");
  2. Properties properties = ConvertUtil.toProperties(map);
  3. LOGGER.debug(JsonUtil.format(properties));

返回:

  1. {"name": "feilong"}

7.5 convert(Object, Class<T>)

toBeConvertedValue 转成指定 targetType 类型的对象.

示例:

  1. ConvertUtil.convert("1", Integer.class) =1
  2. ConvertUtil.convert("", Integer.class) =0
  3. ConvertUtil.convert("1", Long.class) =1

此外,该方法特别适合数组类型的转换,比如 Type[] 转成 Class []:原来的写法:

  1. Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
  2. int length = actualTypeArguments.length;
  3. Class<?>[] klasses = new Class<?>[length];
  4. for (int i = 0, j = length; i < j; ++i){
  5. klasses[i] = (Class<?>) actualTypeArguments[i];
  6. }
  7. return klasses;

现在可以重构成:

  1. Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
  2. return convert(actualTypeArguments, Class[].class);

注意:

  • 如果targetType的转换器没有注册,那么传入的value原样返回, 比如ConvertUtil.convert("zh_CN", Locale.class) 由于找不到converter,那么返回"zh_CN".
  • 如果转换不了,会使用默认值
  • 如果传的 toBeConvertedValuetoBeConvertedValue.getClass().isArray() 或者 Collection

    • 如果 targetType 不是数组 那么会取第一个元素进行转换, 参见AbstractConverter.convert(Class, Object),调用的 AbstractConverter.convertArray(Object) 方法

    • 如果 targetType 是数组 参见 ArrayConverter#convertToType(Class, Object) 会基于targetType 构造一个数组对象,大小长度就是 toBeConvertedValue的大小或者长度, 然后迭代 toBeConvertedValue 依次进行转换