mirror of
https://gitee.com/dromara/hutool.git
synced 2025-05-03 12:18:01 +08:00
fix convert
This commit is contained in:
parent
17e91a6388
commit
c646ba04ef
@ -3,7 +3,7 @@
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# 5.5.0 (2020-11-09)
|
||||
# 5.5.0 (2020-11-11)
|
||||
|
||||
### 新特性
|
||||
* 【core 】 NumberUtil.parseInt等支持123,2.00这类数字(issue#I23ORQ@Gitee)
|
||||
@ -14,6 +14,7 @@
|
||||
* 【poi 】 ExcelWriter增加setCurrentRowToEnd方法(issue#I24A2R@Gitee)
|
||||
* 【core 】 ExcelWriter增加setCurrentRowToEnd方法(issue#I24A2R@Gitee)
|
||||
* 【extra 】 增加表达式引擎封装(ExpressionUtil)(pr#1203@Github)
|
||||
* 【core 】 增加enum转数字支持(issue#I24QZY@Gitee)
|
||||
|
||||
### Bug修复
|
||||
* 【core 】 修复DateUtil.current使用System.nanoTime的问题(issue#1198@Github)
|
||||
@ -24,6 +25,7 @@
|
||||
* 【poi 】 修复Excel07SaxReader读取公式的错误的问题(issue#I23VFL@Gitee)
|
||||
* 【http 】 修复HttpUtil.isHttp判断问题(pr#1208@Github)
|
||||
* 【http 】 修复Snowflake时间回拨导致ID重复的bug(issue#1206@Github)
|
||||
* 【core 】 修复StrUtil.lastIndexOf查找位于首位的字符串找不到的bug(issue#I24RSV@Gitee)
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
@ -15,6 +15,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.DoubleAdder;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* 数字转换器<br>
|
||||
@ -54,17 +55,31 @@ public class NumberConverter extends AbstractConverter<Number> {
|
||||
|
||||
@Override
|
||||
protected Number convertInternal(Object value) {
|
||||
return convertInternal(value, this.targetType);
|
||||
return convert(value, this.targetType, this::convertToStr);
|
||||
}
|
||||
|
||||
private Number convertInternal(Object value, Class<?> targetType) {
|
||||
/**
|
||||
* 转换对象为数字
|
||||
*
|
||||
* @param value 对象值
|
||||
* @param targetType 目标的数字类型
|
||||
* @param toStrFunc 转换为字符串的函数
|
||||
* @return 转换后的数字
|
||||
* @since 5.5.0
|
||||
*/
|
||||
protected static Number convert(Object value, Class<?> targetType, Function<Object, String> toStrFunc) {
|
||||
// 枚举转换为数字默认为其顺序
|
||||
if (value instanceof Enum) {
|
||||
return convert(((Enum<?>) value).ordinal(), targetType, toStrFunc);
|
||||
}
|
||||
|
||||
if (Byte.class == targetType) {
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).byteValue();
|
||||
} else if (value instanceof Boolean) {
|
||||
return BooleanUtil.toByteObj((Boolean) value);
|
||||
}
|
||||
final String valueStr = convertToStr(value);
|
||||
final String valueStr = toStrFunc.apply(value);
|
||||
return StrUtil.isBlank(valueStr) ? null : Byte.valueOf(valueStr);
|
||||
} else if (Short.class == targetType) {
|
||||
if (value instanceof Number) {
|
||||
@ -72,7 +87,7 @@ public class NumberConverter extends AbstractConverter<Number> {
|
||||
} else if (value instanceof Boolean) {
|
||||
return BooleanUtil.toShortObj((Boolean) value);
|
||||
}
|
||||
final String valueStr = convertToStr(value);
|
||||
final String valueStr = toStrFunc.apply((value));
|
||||
return StrUtil.isBlank(valueStr) ? null : Short.valueOf(valueStr);
|
||||
} else if (Integer.class == targetType) {
|
||||
if (value instanceof Number) {
|
||||
@ -80,16 +95,16 @@ public class NumberConverter extends AbstractConverter<Number> {
|
||||
} else if (value instanceof Boolean) {
|
||||
return BooleanUtil.toInteger((Boolean) value);
|
||||
} else if (value instanceof Date) {
|
||||
return (int)((Date) value).getTime();
|
||||
return (int) ((Date) value).getTime();
|
||||
} else if (value instanceof Calendar) {
|
||||
return (int)((Calendar) value).getTimeInMillis();
|
||||
return (int) ((Calendar) value).getTimeInMillis();
|
||||
} else if (value instanceof TemporalAccessor) {
|
||||
return (int)DateUtil.toInstant((TemporalAccessor) value).toEpochMilli();
|
||||
return (int) DateUtil.toInstant((TemporalAccessor) value).toEpochMilli();
|
||||
}
|
||||
final String valueStr = convertToStr(value);
|
||||
final String valueStr = toStrFunc.apply((value));
|
||||
return StrUtil.isBlank(valueStr) ? null : NumberUtil.parseInt(valueStr);
|
||||
} else if (AtomicInteger.class == targetType) {
|
||||
final Number number = convertInternal(value, Integer.class);
|
||||
final Number number = convert(value, Integer.class, toStrFunc);
|
||||
if (null != number) {
|
||||
final AtomicInteger intValue = new AtomicInteger();
|
||||
intValue.set(number.intValue());
|
||||
@ -107,18 +122,18 @@ public class NumberConverter extends AbstractConverter<Number> {
|
||||
} else if (value instanceof TemporalAccessor) {
|
||||
return DateUtil.toInstant((TemporalAccessor) value).toEpochMilli();
|
||||
}
|
||||
final String valueStr = convertToStr(value);
|
||||
final String valueStr = toStrFunc.apply((value));
|
||||
return StrUtil.isBlank(valueStr) ? null : NumberUtil.parseLong(valueStr);
|
||||
} else if (AtomicLong.class == targetType) {
|
||||
final Number number = convertInternal(value, Long.class);
|
||||
final Number number = convert(value, Long.class, toStrFunc);
|
||||
if (null != number) {
|
||||
final AtomicLong longValue = new AtomicLong();
|
||||
longValue.set(number.longValue());
|
||||
return longValue;
|
||||
}
|
||||
}else if (LongAdder.class == targetType) {
|
||||
} else if (LongAdder.class == targetType) {
|
||||
//jdk8 新增
|
||||
final Number number = convertInternal(value, Long.class);
|
||||
final Number number = convert(value, Long.class, toStrFunc);
|
||||
if (null != number) {
|
||||
final LongAdder longValue = new LongAdder();
|
||||
longValue.add(number.longValue());
|
||||
@ -130,7 +145,7 @@ public class NumberConverter extends AbstractConverter<Number> {
|
||||
} else if (value instanceof Boolean) {
|
||||
return BooleanUtil.toFloatObj((Boolean) value);
|
||||
}
|
||||
final String valueStr = convertToStr(value);
|
||||
final String valueStr = toStrFunc.apply((value));
|
||||
return StrUtil.isBlank(valueStr) ? null : Float.valueOf(valueStr);
|
||||
|
||||
} else if (Double.class == targetType) {
|
||||
@ -139,31 +154,31 @@ public class NumberConverter extends AbstractConverter<Number> {
|
||||
} else if (value instanceof Boolean) {
|
||||
return BooleanUtil.toDoubleObj((Boolean) value);
|
||||
}
|
||||
final String valueStr = convertToStr(value);
|
||||
final String valueStr = toStrFunc.apply((value));
|
||||
return StrUtil.isBlank(valueStr) ? null : Double.valueOf(valueStr);
|
||||
}else if (DoubleAdder.class == targetType) {
|
||||
} else if (DoubleAdder.class == targetType) {
|
||||
//jdk8 新增
|
||||
final Number number = convertInternal(value, Long.class);
|
||||
final Number number = convert(value, Long.class, toStrFunc);
|
||||
if (null != number) {
|
||||
final DoubleAdder doubleAdder = new DoubleAdder();
|
||||
doubleAdder.add(number.doubleValue());
|
||||
return doubleAdder;
|
||||
}
|
||||
} else if (BigDecimal.class == targetType) {
|
||||
return toBigDecimal(value);
|
||||
return toBigDecimal(value, toStrFunc);
|
||||
} else if (BigInteger.class == targetType) {
|
||||
return toBigInteger(value);
|
||||
return toBigInteger(value, toStrFunc);
|
||||
} else if (Number.class == targetType) {
|
||||
if (value instanceof Number) {
|
||||
return (Number) value;
|
||||
} else if (value instanceof Boolean) {
|
||||
return BooleanUtil.toInteger((Boolean) value);
|
||||
}
|
||||
final String valueStr = convertToStr(value);
|
||||
final String valueStr = toStrFunc.apply((value));
|
||||
return StrUtil.isBlank(valueStr) ? null : NumberUtil.parseNumber(valueStr);
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException(StrUtil.format("Unsupport Number type: {}", this.targetType.getName()));
|
||||
throw new UnsupportedOperationException(StrUtil.format("Unsupport Number type: {}", targetType.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -171,10 +186,11 @@ public class NumberConverter extends AbstractConverter<Number> {
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param value 被转换的值
|
||||
* @param toStrFunc 转换为字符串的函数规则
|
||||
* @return 结果
|
||||
*/
|
||||
private BigDecimal toBigDecimal(Object value) {
|
||||
private static BigDecimal toBigDecimal(Object value, Function<Object, String> toStrFunc) {
|
||||
if (value instanceof Number) {
|
||||
return NumberUtil.toBigDecimal((Number) value);
|
||||
} else if (value instanceof Boolean) {
|
||||
@ -182,7 +198,7 @@ public class NumberConverter extends AbstractConverter<Number> {
|
||||
}
|
||||
|
||||
//对于Double类型,先要转换为String,避免精度问题
|
||||
return NumberUtil.toBigDecimal(convertToStr(value));
|
||||
return NumberUtil.toBigDecimal(toStrFunc.apply(value));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -190,25 +206,26 @@ public class NumberConverter extends AbstractConverter<Number> {
|
||||
* 如果给定的值为空,或者转换失败,返回默认值<br>
|
||||
* 转换失败不会报错
|
||||
*
|
||||
* @param value 被转换的值
|
||||
* @param value 被转换的值
|
||||
* @param toStrFunc 转换为字符串的函数规则
|
||||
* @return 结果
|
||||
*/
|
||||
private BigInteger toBigInteger(Object value) {
|
||||
private static BigInteger toBigInteger(Object value, Function<Object, String> toStrFunc) {
|
||||
if (value instanceof Long) {
|
||||
return BigInteger.valueOf((Long) value);
|
||||
} else if (value instanceof Boolean) {
|
||||
return BigInteger.valueOf((boolean) value ? 1 : 0);
|
||||
}
|
||||
|
||||
return NumberUtil.toBigInteger(convertToStr(value));
|
||||
return NumberUtil.toBigInteger(toStrFunc.apply(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String convertToStr(Object value) {
|
||||
String result = StrUtil.trim(super.convertToStr(value));
|
||||
if(StrUtil.isNotEmpty(result)){
|
||||
if (StrUtil.isNotEmpty(result)) {
|
||||
final char c = Character.toUpperCase(result.charAt(result.length() - 1));
|
||||
if(c == 'D' || c == 'L' || c == 'F'){
|
||||
if (c == 'D' || c == 'L' || c == 'F') {
|
||||
// 类型标识形式(例如123.6D)
|
||||
return StrUtil.subPre(result, -1);
|
||||
}
|
||||
|
@ -1,15 +1,12 @@
|
||||
package cn.hutool.core.convert.impl;
|
||||
|
||||
import cn.hutool.core.convert.AbstractConverter;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.convert.ConvertException;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.BooleanUtil;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* 原始类型转换器<br>
|
||||
@ -49,114 +46,7 @@ public class PrimitiveConverter extends AbstractConverter<Object> {
|
||||
|
||||
@Override
|
||||
protected Object convertInternal(Object value) {
|
||||
if (byte.class == this.targetType) {
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).byteValue();
|
||||
} else if (value instanceof Boolean) {
|
||||
return BooleanUtil.toByte((Boolean) value);
|
||||
}
|
||||
final String valueStr = convertToStr(value);
|
||||
if (StrUtil.isBlank(valueStr)) {
|
||||
return 0;
|
||||
}
|
||||
return Byte.parseByte(valueStr);
|
||||
|
||||
} else if (short.class == this.targetType) {
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).shortValue();
|
||||
} else if (value instanceof Boolean) {
|
||||
return BooleanUtil.toShort((Boolean) value);
|
||||
}
|
||||
final String valueStr = convertToStr(value);
|
||||
if (StrUtil.isBlank(valueStr)) {
|
||||
return 0;
|
||||
}
|
||||
return Short.parseShort(valueStr);
|
||||
|
||||
} else if (int.class == this.targetType) {
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).intValue();
|
||||
} else if (value instanceof Boolean) {
|
||||
return BooleanUtil.toInt((Boolean) value);
|
||||
} else if (value instanceof Date) {
|
||||
return ((Date) value).getTime();
|
||||
} else if (value instanceof Calendar) {
|
||||
return ((Calendar) value).getTimeInMillis();
|
||||
} else if (value instanceof TemporalAccessor) {
|
||||
return DateUtil.toInstant((TemporalAccessor) value).toEpochMilli();
|
||||
}
|
||||
|
||||
final String valueStr = convertToStr(value);
|
||||
if (StrUtil.isBlank(valueStr)) {
|
||||
return 0;
|
||||
}
|
||||
return NumberUtil.parseInt(valueStr);
|
||||
|
||||
} else if (long.class == this.targetType) {
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).longValue();
|
||||
} else if (value instanceof Boolean) {
|
||||
return BooleanUtil.toLong((Boolean) value);
|
||||
} else if (value instanceof Date) {
|
||||
return ((Date) value).getTime();
|
||||
} else if (value instanceof Calendar) {
|
||||
return ((Calendar) value).getTimeInMillis();
|
||||
} else if (value instanceof TemporalAccessor) {
|
||||
return DateUtil.toInstant((TemporalAccessor) value).toEpochMilli();
|
||||
}
|
||||
|
||||
final String valueStr = convertToStr(value);
|
||||
if (StrUtil.isBlank(valueStr)) {
|
||||
return 0;
|
||||
}
|
||||
return NumberUtil.parseLong(valueStr);
|
||||
|
||||
} else if (float.class == this.targetType) {
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).floatValue();
|
||||
} else if (value instanceof Boolean) {
|
||||
return BooleanUtil.toFloat((Boolean) value);
|
||||
}
|
||||
final String valueStr = convertToStr(value);
|
||||
if (StrUtil.isBlank(valueStr)) {
|
||||
return 0;
|
||||
}
|
||||
return Float.parseFloat(valueStr);
|
||||
|
||||
} else if (double.class == this.targetType) {
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).doubleValue();
|
||||
} else if (value instanceof Boolean) {
|
||||
return BooleanUtil.toDouble((Boolean) value);
|
||||
}
|
||||
final String valueStr = convertToStr(value);
|
||||
if (StrUtil.isBlank(valueStr)) {
|
||||
return 0;
|
||||
}
|
||||
return Double.parseDouble(valueStr);
|
||||
|
||||
} else if (char.class == this.targetType) {
|
||||
if (value instanceof Character) {
|
||||
//noinspection UnnecessaryUnboxing
|
||||
return ((Character) value).charValue();
|
||||
} else if (value instanceof Boolean) {
|
||||
return BooleanUtil.toChar((Boolean) value);
|
||||
}
|
||||
final String valueStr = convertToStr(value);
|
||||
if (StrUtil.isBlank(valueStr)) {
|
||||
return 0;
|
||||
}
|
||||
return valueStr.charAt(0);
|
||||
} else if (boolean.class == this.targetType) {
|
||||
if (value instanceof Boolean) {
|
||||
//noinspection UnnecessaryUnboxing
|
||||
return ((Boolean) value).booleanValue();
|
||||
}
|
||||
final String valueStr = convertToStr(value);
|
||||
return BooleanUtil.toBoolean(valueStr);
|
||||
}
|
||||
|
||||
throw new ConvertException("Unsupported target type: {}", this.targetType);
|
||||
return PrimitiveConverter.convert(value, this.targetType, this::convertToStr);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -169,4 +59,34 @@ public class PrimitiveConverter extends AbstractConverter<Object> {
|
||||
public Class<Object> getTargetType() {
|
||||
return (Class<Object>) this.targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将指定值转换为原始类型的值
|
||||
* @param value 值
|
||||
* @param primitiveClass 原始类型
|
||||
* @param toStringFunc 当无法直接转换时,转为字符串后再转换的函数
|
||||
* @return 转换结果
|
||||
* @since 5.5.0
|
||||
*/
|
||||
protected static Object convert(Object value, Class<?> primitiveClass, Function<Object, String> toStringFunc) {
|
||||
if (byte.class == primitiveClass) {
|
||||
return ObjectUtil.defaultIfNull(NumberConverter.convert(value, Byte.class, toStringFunc), 0);
|
||||
} else if (short.class == primitiveClass) {
|
||||
return ObjectUtil.defaultIfNull(NumberConverter.convert(value, Short.class, toStringFunc), 0);
|
||||
} else if (int.class == primitiveClass) {
|
||||
return ObjectUtil.defaultIfNull(NumberConverter.convert(value, Integer.class, toStringFunc), 0);
|
||||
} else if (long.class == primitiveClass) {
|
||||
return ObjectUtil.defaultIfNull(NumberConverter.convert(value, Long.class, toStringFunc), 0);
|
||||
} else if (float.class == primitiveClass) {
|
||||
return ObjectUtil.defaultIfNull(NumberConverter.convert(value, Float.class, toStringFunc), 0);
|
||||
} else if (double.class == primitiveClass) {
|
||||
return ObjectUtil.defaultIfNull(NumberConverter.convert(value, Double.class, toStringFunc), 0);
|
||||
} else if (char.class == primitiveClass) {
|
||||
return Convert.convert(Character.class, value);
|
||||
} else if (boolean.class == primitiveClass) {
|
||||
return Convert.convert(Boolean.class, value);
|
||||
}
|
||||
|
||||
throw new ConvertException("Unsupported target type: {}", primitiveClass);
|
||||
}
|
||||
}
|
||||
|
@ -4019,7 +4019,7 @@ public class StrUtil {
|
||||
return str.toString().lastIndexOf(searchStr.toString(), fromIndex);
|
||||
}
|
||||
|
||||
for (int i = fromIndex; i > 0; i--) {
|
||||
for (int i = fromIndex; i >= 0; i--) {
|
||||
if (isSubEquals(str, i, searchStr, 0, searchStr.length(), true)) {
|
||||
return i;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import cn.hutool.core.annotation.Alias;
|
||||
import cn.hutool.core.bean.copier.CopyOptions;
|
||||
import cn.hutool.core.bean.copier.ValueProvider;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Console;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
|
@ -2,6 +2,7 @@ package cn.hutool.core.convert;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
@ -253,4 +254,28 @@ public class ConvertTest {
|
||||
private String cName;
|
||||
private String version;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enumToIntTest(){
|
||||
final Integer integer = Convert.toInt(BuildingType.CUO);
|
||||
Assert.assertEquals(1, integer.intValue());
|
||||
}
|
||||
|
||||
@Getter
|
||||
public enum BuildingType {
|
||||
PING(1, "平层"),
|
||||
CUO(2, "错层"),
|
||||
YUE(3, "跃层"),
|
||||
FUSHI(4, "复式"),
|
||||
KAIJIAN(5, "开间"),
|
||||
OTHER(6, "其他");
|
||||
|
||||
private final int id;
|
||||
private final String name;
|
||||
|
||||
BuildingType(int id, String name){
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -164,6 +164,7 @@ public class StrUtilTest {
|
||||
Assert.assertEquals(-1, StrUtil.lastIndexOfIgnoreCase("aabaabaa", "B", -1));
|
||||
Assert.assertEquals(2, StrUtil.lastIndexOfIgnoreCase("aabaabaa", "", 2));
|
||||
Assert.assertEquals(3, StrUtil.lastIndexOfIgnoreCase("abc", "", 9));
|
||||
Assert.assertEquals(0, StrUtil.lastIndexOfIgnoreCase("AAAcsd", "aaa"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Loading…
Reference in New Issue
Block a user