fix methoda

This commit is contained in:
Looly 2020-08-02 19:26:24 +08:00
parent c47272922b
commit d07feb9065
9 changed files with 239 additions and 134 deletions

View File

@ -9,8 +9,11 @@
* 【socket】 对NioServer和NioClient改造pr#992@Github
* 【core 】 StrUtil增加filter方法pr#149@Gitee
* 【core 】 DateUtil增加beginOfWeek重载
* 【core 】 将有歧义的BeanUtil.mapToBean方法置为过期使用toBean方法
### Bug修复#
* 【core 】 修复原始类型转换时,转换失败没有抛出异常的问题
* 【core 】 修复BeanUtil.mapToBean中bean的class非空构造无法实例化问题
-------------------------------------------------------------------------------------------------------------

View File

@ -52,7 +52,7 @@ public class BeanUtil {
*
* @param clazz 待测试类
* @return 是否为可读的Bean对象
* @see #hasGetter(Class)
* @see #hasGetter(Class)
* @see #hasPublicField(Class)
*/
public static boolean isReadableBean(Class<?> clazz) {
@ -342,9 +342,11 @@ public class BeanUtil {
* @param beanClass Bean Class
* @param isIgnoreError 是否忽略注入错误
* @return Bean
* @deprecated 请使用 {@link #toBean(Object, Class)} {@link #toBeanIgnoreError(Object, Class)}
*/
@Deprecated
public static <T> T mapToBean(Map<?, ?> map, Class<T> beanClass, boolean isIgnoreError) {
return fillBeanWithMap(map, ReflectUtil.newInstance(beanClass), isIgnoreError);
return fillBeanWithMap(map, ReflectUtil.newInstanceIfPossible(beanClass), isIgnoreError);
}
/**
@ -356,9 +358,11 @@ public class BeanUtil {
* @param beanClass Bean Class
* @param isIgnoreError 是否忽略注入错误
* @return Bean
* @deprecated 请使用 {@link #toBeanIgnoreCase(Object, Class, boolean)}
*/
@Deprecated
public static <T> T mapToBeanIgnoreCase(Map<?, ?> map, Class<T> beanClass, boolean isIgnoreError) {
return fillBeanWithMapIgnoreCase(map, ReflectUtil.newInstance(beanClass), isIgnoreError);
return fillBeanWithMapIgnoreCase(map, ReflectUtil.newInstanceIfPossible(beanClass), isIgnoreError);
}
/**
@ -369,9 +373,25 @@ public class BeanUtil {
* @param beanClass Bean Class
* @param copyOptions 转Bean选项
* @return Bean
* @deprecated 请使用 {@link #toBean(Object, Class, CopyOptions)}
*/
@Deprecated
public static <T> T mapToBean(Map<?, ?> map, Class<T> beanClass, CopyOptions copyOptions) {
return fillBeanWithMap(map, ReflectUtil.newInstance(beanClass), copyOptions);
return fillBeanWithMap(map, ReflectUtil.newInstanceIfPossible(beanClass), copyOptions);
}
/**
* Map转换为Bean对象
*
* @param <T> Bean类型
* @param map {@link Map}
* @param beanClass Bean Class
* @param isToCamelCase 是否将Map中的下划线风格key转换为驼峰风格
* @param copyOptions 转Bean选项
* @return Bean
*/
public static <T> T mapToBean(Map<?, ?> map, Class<T> beanClass, boolean isToCamelCase, CopyOptions copyOptions) {
return fillBeanWithMap(map, ReflectUtil.newInstanceIfPossible(beanClass), isToCamelCase, copyOptions);
}
// --------------------------------------------------------------------------------------------- fillBeanWithMap
@ -447,7 +467,8 @@ public class BeanUtil {
if (isToCamelCase) {
map = MapUtil.toCamelCaseMap(map);
}
return BeanCopier.create(map, bean, copyOptions).copy();
copyProperties(map, bean, copyOptions);
return bean;
}
// --------------------------------------------------------------------------------------------- fillBean
@ -465,6 +486,36 @@ public class BeanUtil {
return toBean(source, clazz, null);
}
/**
* 对象或Map转Bean忽略字段转换时发生的异常
*
* @param <T> 转换的Bean类型
* @param source Bean对象或Map
* @param clazz 目标的Bean类型
* @return Bean对象
* @since 5.4.0
*/
public static <T> T toBeanIgnoreError(Object source, Class<T> clazz) {
return toBean(source, clazz, CopyOptions.create().setIgnoreError(true));
}
/**
* 对象或Map转Bean忽略字段转换时发生的异常
*
* @param <T> 转换的Bean类型
* @param source Bean对象或Map
* @param clazz 目标的Bean类型
* @param ignoreError 是否忽略注入错误
* @return Bean对象
* @since 5.4.0
*/
public static <T> T toBeanIgnoreCase(Object source, Class<T> clazz, boolean ignoreError) {
return toBean(source, clazz,
CopyOptions.create()
.setIgnoreCase(true)
.setIgnoreError(ignoreError));
}
/**
* 对象或Map转Bean
*
@ -491,7 +542,7 @@ public class BeanUtil {
* @return Bean
*/
public static <T> T toBean(Class<T> beanClass, ValueProvider<String> valueProvider, CopyOptions copyOptions) {
return fillBean(ReflectUtil.newInstance(beanClass), valueProvider, copyOptions);
return fillBean(ReflectUtil.newInstanceIfPossible(beanClass), valueProvider, copyOptions);
}
/**
@ -608,9 +659,9 @@ public class BeanUtil {
/**
* 按照Bean对象属性创建对应的Class对象并忽略某些属性
*
* @param <T> 对象类型
* @param source 源Bean对象
* @param tClass 目标Class
* @param <T> 对象类型
* @param source 源Bean对象
* @param tClass 目标Class
* @param ignoreProperties 不拷贝的的属性列表
* @return 目标对象
*/
@ -690,7 +741,7 @@ public class BeanUtil {
final Field[] fields = ReflectUtil.getFields(bean.getClass());
for (Field field : fields) {
if(ModifierUtil.isStatic(field)){
if (ModifierUtil.isStatic(field)) {
continue;
}
if (ignoreFields != null && ArrayUtil.containsIgnoreCase(ignoreFields, field.getName())) {
@ -737,7 +788,7 @@ public class BeanUtil {
public static boolean isEmpty(Object bean, String... ignoreFiledNames) {
if (null != bean) {
for (Field field : ReflectUtil.getFields(bean.getClass())) {
if(ModifierUtil.isStatic(field)){
if (ModifierUtil.isStatic(field)) {
continue;
}
if ((false == ArrayUtil.contains(ignoreFiledNames, field.getName()))
@ -763,7 +814,7 @@ public class BeanUtil {
return true;
}
for (Field field : ReflectUtil.getFields(bean.getClass())) {
if(ModifierUtil.isStatic(field)){
if (ModifierUtil.isStatic(field)) {
continue;
}
if ((false == ArrayUtil.contains(ignoreFiledNames, field.getName()))//

View File

@ -609,9 +609,8 @@ public class Convert {
* @since 4.0.7
* @throws ConvertException 转换器不存在
*/
@SuppressWarnings("unchecked")
public static <T> T convertByClassName(String className, Object value) throws ConvertException{
return (T) convert(ClassUtil.loadClass(className), value);
return convert(ClassUtil.loadClass(className), value);
}
/**

View File

@ -5,6 +5,7 @@ import cn.hutool.core.bean.copier.BeanCopier;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.bean.copier.ValueProvider;
import cn.hutool.core.convert.AbstractConverter;
import cn.hutool.core.convert.ConvertException;
import cn.hutool.core.map.MapProxy;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
@ -79,7 +80,8 @@ public class BeanConverter<T> extends AbstractConverter<T> {
// 尝试反序列化
return ObjectUtil.deserialize((byte[])value);
}
return null;
throw new ConvertException("Unsupported source type: {}", value.getClass());
}
@Override

View File

@ -1,6 +1,7 @@
package cn.hutool.core.convert.impl;
import cn.hutool.core.convert.AbstractConverter;
import cn.hutool.core.convert.ConvertException;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.NumberUtil;
@ -48,117 +49,114 @@ public class PrimitiveConverter extends AbstractConverter<Object> {
@Override
protected Object convertInternal(Object value) {
try {
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();
}
String valueStr = convertToStr(value);
return BooleanUtil.toBoolean(valueStr);
if (byte.class == this.targetType) {
if (value instanceof Number) {
return ((Number) value).byteValue();
} else if (value instanceof Boolean) {
return BooleanUtil.toByte((Boolean) value);
}
} catch (Exception e) {
// Ignore Exception
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);
}
return 0;
throw new ConvertException("Unsupported target type: {}", this.targetType);
}
@Override

View File

@ -178,7 +178,7 @@ public class Dict extends LinkedHashMap<String, Object> implements BasicTypeGett
* @return vo
*/
public <T> T toBean(Class<T> clazz) {
return BeanUtil.mapToBean(this, clazz, false);
return BeanUtil.toBean(this, clazz);
}
/**
@ -189,7 +189,7 @@ public class Dict extends LinkedHashMap<String, Object> implements BasicTypeGett
* @return vo
*/
public <T> T toBeanIgnoreCase(Class<T> clazz) {
return BeanUtil.mapToBeanIgnoreCase(this, clazz, false);
return BeanUtil.toBeanIgnoreCase(this, clazz, false);
}
/**

View File

@ -1,12 +1,12 @@
package cn.hutool.core.text.replacer;
import cn.hutool.core.text.StrBuilder;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import cn.hutool.core.text.StrBuilder;
/**
* 查找替换器通过查找指定关键字替换对应的值
*
@ -27,8 +27,8 @@ public class LookupReplacer extends StrReplacer {
* @param lookup 被查找的键值对
*/
public LookupReplacer(String[]... lookup) {
this.lookupMap = new HashMap<String, String>();
this.prefixSet = new HashSet<Character>();
this.lookupMap = new HashMap<>();
this.prefixSet = new HashSet<>();
int minLength = Integer.MAX_VALUE;
int maxLength = 0;

View File

@ -92,13 +92,29 @@ public class BeanUtilTest {
Assert.assertFalse(map.containsKey("SUBNAME"));
}
/**
* 忽略转换错误测试
*/
@Test
public void toBeanIgnoreErrorTest(){
HashMap<String, Object> map = CollUtil.newHashMap();
map.put("name", "Joe");
// 错误的类型此处忽略
map.put("age", "aaaaaa");
Person person = BeanUtil.toBeanIgnoreError(map, Person.class);
Assert.assertEquals("Joe", person.getName());
// 错误的类型不copy这个字段使用对象创建的默认值
Assert.assertEquals(0, person.getAge());
}
@Test
public void mapToBeanIgnoreCaseTest() {
HashMap<String, Object> map = CollUtil.newHashMap();
map.put("Name", "Joe");
map.put("aGe", 12);
Person person = BeanUtil.mapToBeanIgnoreCase(map, Person.class, false);
Person person = BeanUtil.toBeanIgnoreCase(map, Person.class, false);
Assert.assertEquals("Joe", person.getName());
Assert.assertEquals(12, person.getAge());
}
@ -114,7 +130,7 @@ public class BeanUtilTest {
mapping.put("a_name", "name");
mapping.put("b_age", "age");
Person person = BeanUtil.mapToBean(map, Person.class, CopyOptions.create().setFieldMapping(mapping));
Person person = BeanUtil.toBean(map, Person.class, CopyOptions.create().setFieldMapping(mapping));
Assert.assertEquals("Joe", person.getName());
Assert.assertEquals(12, person.getAge());
}
@ -128,11 +144,22 @@ public class BeanUtilTest {
map.put("name", "Joe");
map.put("age", 12);
Person2 person = BeanUtil.mapToBean(map, Person2.class, CopyOptions.create());
// 非空构造也可以实例化成功
Person2 person = BeanUtil.toBean(map, Person2.class, CopyOptions.create());
Assert.assertEquals("Joe", person.name);
Assert.assertEquals(12, person.age);
}
/**
* 测试在不忽略错误情况下转换失败需要报错
*/
@Test(expected = NumberFormatException.class)
public void mapToBeanWinErrorTest() {
Map<String, String> map = new HashMap<>();
map.put("age", "哈哈");
Person user = BeanUtil.toBean(map, Person.class);
}
@Test
public void beanToMapTest() {
SubPerson person = new SubPerson();
@ -181,7 +208,7 @@ public class BeanUtilTest {
map.put("aliasSubName", "sub名字");
map.put("slow", true);
final SubPersonWithAlias subPersonWithAlias = BeanUtil.mapToBean(map, SubPersonWithAlias.class, false);
final SubPersonWithAlias subPersonWithAlias = BeanUtil.toBean(map, SubPersonWithAlias.class);
Assert.assertEquals("sub名字", subPersonWithAlias.getSubName());
}
@ -345,6 +372,13 @@ public class BeanUtilTest {
}
public static class Person2 {
public Person2(String name, int age, String openid) {
this.name = name;
this.age = age;
this.openid = openid;
}
public String name;
public int age;
public String openid;

View File

@ -0,0 +1,18 @@
package cn.hutool.core.convert;
import org.junit.Assert;
import org.junit.Test;
public class PrimitiveConvertTest {
@Test
public void toIntTest(){
final int convert = Convert.convert(int.class, "123");
Assert.assertEquals(123, convert);
}
@Test(expected = NumberFormatException.class)
public void toIntErrorTest(){
final int convert = Convert.convert(int.class, "aaaa");
}
}