mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
add method
This commit is contained in:
parent
7b4e1c775a
commit
7b0e6dddc0
@ -3,7 +3,7 @@
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
# 5.4.0 (2020-08-04)
|
||||
# 5.4.0 (2020-08-06)
|
||||
|
||||
### 新特性
|
||||
* 【socket】 对NioServer和NioClient改造(pr#992@Github)
|
||||
@ -12,11 +12,13 @@
|
||||
* 【core 】 将有歧义的BeanUtil.mapToBean方法置为过期(使用toBean方法)
|
||||
* 【core 】 添加WatchAction(对Watcher的抽象)
|
||||
* 【core 】 修改UUID正则,更加严谨(issue#I1Q1IW@Gitee)
|
||||
* 【core 】 ArrayUtil增加isAllNull方法(issue#1004@Github)
|
||||
|
||||
### Bug修复#
|
||||
* 【core 】 修复原始类型转换时,转换失败没有抛出异常的问题
|
||||
* 【core 】 修复BeanUtil.mapToBean中bean的class非空构造无法实例化问题
|
||||
* 【core 】 修复NamedSql多个连续变量出现替换问题
|
||||
* 【core 】 修复Bean重名字段(大小写区别)获取数据出错的问题(issue#I1QBQ4@Gitee)
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
@ -145,10 +145,13 @@ public class BeanDesc implements Serializable {
|
||||
* @return this
|
||||
*/
|
||||
private BeanDesc init() {
|
||||
final Method[] methods = ReflectUtil.getMethods(this.beanClass);
|
||||
PropDesc prop;
|
||||
for (Field field : ReflectUtil.getFields(this.beanClass)) {
|
||||
if (false == ModifierUtil.isStatic(field)) {
|
||||
//只针对非static属性
|
||||
this.propMap.put(ReflectUtil.getFieldName(field), createProp(field));
|
||||
prop = createProp(field, methods);
|
||||
this.propMap.put(prop.getFieldName(), prop);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
@ -165,21 +168,45 @@ public class BeanDesc implements Serializable {
|
||||
* 4. Setter忽略参数值与字段值不匹配的情况,因此有多个参数类型的重载时,会调用首次匹配的
|
||||
* </pre>
|
||||
*
|
||||
* @param field 字段
|
||||
* @param field 字段
|
||||
* @param methods 类中所有的方法
|
||||
* @return {@link PropDesc}
|
||||
* @since 4.0.2
|
||||
*/
|
||||
private PropDesc createProp(Field field) {
|
||||
private PropDesc createProp(Field field, Method[] methods) {
|
||||
final PropDesc prop = findProp(field, methods, false);
|
||||
// 忽略大小写重新匹配一次
|
||||
if (null == prop.getter || null == prop.setter) {
|
||||
final PropDesc propIgnoreCase = findProp(field, methods, true);
|
||||
if (null == prop.getter) {
|
||||
prop.getter = propIgnoreCase.getter;
|
||||
}
|
||||
if (null == prop.setter) {
|
||||
prop.setter = propIgnoreCase.setter;
|
||||
}
|
||||
}
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找字段对应的Getter和Setter方法
|
||||
*
|
||||
* @param field 字段
|
||||
* @param methods 类中所有的方法
|
||||
* @param ignoreCase 是否忽略大小写匹配
|
||||
* @return PropDesc
|
||||
*/
|
||||
private PropDesc findProp(Field field, Method[] methods, boolean ignoreCase) {
|
||||
final String fieldName = field.getName();
|
||||
final Class<?> fieldType = field.getType();
|
||||
final boolean isBooeanField = BooleanUtil.isBoolean(fieldType);
|
||||
final boolean isBooleanField = BooleanUtil.isBoolean(fieldType);
|
||||
|
||||
Method getter = null;
|
||||
Method setter = null;
|
||||
|
||||
String methodName;
|
||||
Class<?>[] parameterTypes;
|
||||
for (Method method : ReflectUtil.getMethods(this.beanClass)) {
|
||||
for (Method method : methods) {
|
||||
parameterTypes = method.getParameterTypes();
|
||||
if (parameterTypes.length > 1) {
|
||||
// 多于1个参数说明非Getter或Setter
|
||||
@ -189,11 +216,11 @@ public class BeanDesc implements Serializable {
|
||||
methodName = method.getName();
|
||||
if (parameterTypes.length == 0) {
|
||||
// 无参数,可能为Getter方法
|
||||
if (isMatchGetter(methodName, fieldName, isBooeanField)) {
|
||||
if (isMatchGetter(methodName, fieldName, isBooleanField, ignoreCase)) {
|
||||
// 方法名与字段名匹配,则为Getter方法
|
||||
getter = method;
|
||||
}
|
||||
} else if (isMatchSetter(methodName, fieldName, isBooeanField)) {
|
||||
} else if (isMatchSetter(methodName, fieldName, isBooleanField, ignoreCase)) {
|
||||
// 只有一个参数的情况下方法名与字段名对应匹配,则为Setter方法
|
||||
setter = method;
|
||||
}
|
||||
@ -202,6 +229,7 @@ public class BeanDesc implements Serializable {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new PropDesc(field, getter, setter);
|
||||
}
|
||||
|
||||
@ -218,15 +246,20 @@ public class BeanDesc implements Serializable {
|
||||
* name -》 getName
|
||||
* </pre>
|
||||
*
|
||||
* @param methodName 方法名
|
||||
* @param fieldName 字段名
|
||||
* @param isBooeanField 是否为Boolean类型字段
|
||||
* @param methodName 方法名
|
||||
* @param fieldName 字段名
|
||||
* @param isBooleanField 是否为Boolean类型字段
|
||||
* @param ignoreCase 匹配是否忽略大小写
|
||||
* @return 是否匹配
|
||||
*/
|
||||
private boolean isMatchGetter(String methodName, String fieldName, boolean isBooeanField) {
|
||||
private boolean isMatchGetter(String methodName, String fieldName, boolean isBooleanField, boolean ignoreCase) {
|
||||
// 全部转为小写,忽略大小写比较
|
||||
methodName = methodName.toLowerCase();
|
||||
fieldName = fieldName.toLowerCase();
|
||||
if (ignoreCase) {
|
||||
methodName = methodName.toLowerCase();
|
||||
fieldName = fieldName.toLowerCase();
|
||||
} else {
|
||||
fieldName = StrUtil.upperFirst(fieldName);
|
||||
}
|
||||
|
||||
if (false == methodName.startsWith("get") && false == methodName.startsWith("is")) {
|
||||
// 非标准Getter方法
|
||||
@ -238,7 +271,7 @@ public class BeanDesc implements Serializable {
|
||||
}
|
||||
|
||||
// 针对Boolean类型特殊检查
|
||||
if (isBooeanField) {
|
||||
if (isBooleanField) {
|
||||
if (fieldName.startsWith("is")) {
|
||||
// 字段已经是is开头
|
||||
if (methodName.equals(fieldName) // isName -》 isName
|
||||
@ -268,12 +301,13 @@ public class BeanDesc implements Serializable {
|
||||
* name -》 setName
|
||||
* </pre>
|
||||
*
|
||||
* @param methodName 方法名
|
||||
* @param fieldName 字段名
|
||||
* @param isBooeanField 是否为Boolean类型字段
|
||||
* @param methodName 方法名
|
||||
* @param fieldName 字段名
|
||||
* @param isBooleanField 是否为Boolean类型字段
|
||||
* @param ignoreCase 匹配是否忽略大小写
|
||||
* @return 是否匹配
|
||||
*/
|
||||
private boolean isMatchSetter(String methodName, String fieldName, boolean isBooeanField) {
|
||||
private boolean isMatchSetter(String methodName, String fieldName, boolean isBooleanField, boolean ignoreCase) {
|
||||
// 全部转为小写,忽略大小写比较
|
||||
methodName = methodName.toLowerCase();
|
||||
fieldName = fieldName.toLowerCase();
|
||||
@ -284,7 +318,7 @@ public class BeanDesc implements Serializable {
|
||||
}
|
||||
|
||||
// 针对Boolean类型特殊检查
|
||||
if (isBooeanField && fieldName.startsWith("is")) {
|
||||
if (isBooleanField && fieldName.startsWith("is")) {
|
||||
// 字段是is开头
|
||||
if (methodName.equals("set" + StrUtil.removePrefix(fieldName, "is"))// isName -》 setName
|
||||
|| methodName.equals("set" + fieldName)// isName -》 setIsName
|
||||
@ -312,11 +346,11 @@ public class BeanDesc implements Serializable {
|
||||
/**
|
||||
* Getter方法
|
||||
*/
|
||||
private final Method getter;
|
||||
private Method getter;
|
||||
/**
|
||||
* Setter方法
|
||||
*/
|
||||
private final Method setter;
|
||||
private Method setter;
|
||||
|
||||
/**
|
||||
* 构造<br>
|
||||
@ -449,11 +483,11 @@ public class BeanDesc implements Serializable {
|
||||
boolean isTransient = ModifierUtil.hasModifier(this.field, ModifierUtil.ModifierType.TRANSIENT);
|
||||
|
||||
// 检查Getter方法
|
||||
if(false == isTransient && null != this.getter){
|
||||
if (false == isTransient && null != this.getter) {
|
||||
isTransient = ModifierUtil.hasModifier(this.getter, ModifierUtil.ModifierType.TRANSIENT);
|
||||
|
||||
// 检查注解
|
||||
if(false == isTransient){
|
||||
if (false == isTransient) {
|
||||
isTransient = null != AnnotationUtil.getAnnotation(this.getter, Transient.class);
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ public class TemporalAccessorConverter extends AbstractConverter<TemporalAccesso
|
||||
* @param targetType 目标类型
|
||||
*/
|
||||
public TemporalAccessorConverter(Class<?> targetType) {
|
||||
this.targetType = targetType;
|
||||
this(targetType, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -278,33 +278,12 @@ public class ArrayUtil {
|
||||
* @param <T> 数组元素类型
|
||||
* @param array 被检查的数组
|
||||
* @return 多个字段是否全为null
|
||||
* @since 5.3.11
|
||||
* @author dahuoyzs
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> boolean allNull(T... array) {
|
||||
if (isNotEmpty(array)) {
|
||||
for (T element : array) {
|
||||
if (null != element) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 多个字段是否全为null
|
||||
*
|
||||
* @param <T> 数组元素类型
|
||||
* @param array 被检查的数组
|
||||
* @return 多个字段是否全为null
|
||||
* @since 5.3.11
|
||||
* @since 5.4.0
|
||||
* @author dahuoyzs
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> boolean isAllNull(T... array) {
|
||||
return allNull(array);
|
||||
return null == firstNonNull(array);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -391,6 +391,14 @@ public class DateUtilTest {
|
||||
Assert.assertEquals("2019-06-01 19:45:43", dateTime.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseTest8() {
|
||||
String str = "2020-06-28T02:14:13.000Z";
|
||||
DateTime dateTime = DateUtil.parse(str);
|
||||
assert dateTime != null;
|
||||
Assert.assertEquals("2020-06-28 02:14:13", dateTime.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseAndOffsetTest() {
|
||||
// 检查UTC时间偏移是否准确
|
||||
|
17
hutool-core/src/test/java/cn/hutool/core/lang/TupleTest.java
Normal file
17
hutool-core/src/test/java/cn/hutool/core/lang/TupleTest.java
Normal file
@ -0,0 +1,17 @@
|
||||
package cn.hutool.core.lang;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class TupleTest {
|
||||
|
||||
@Test
|
||||
public void hashCodeTest(){
|
||||
final Tuple tuple = new Tuple(Locale.getDefault(), TimeZone.getDefault());
|
||||
final Tuple tuple2 = new Tuple(Locale.getDefault(), TimeZone.getDefault());
|
||||
Assert.assertEquals(tuple, tuple2);
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@ public class StrUtilTest {
|
||||
|
||||
@Test
|
||||
public void isBlankTest2() {
|
||||
String blank = "\u202a";
|
||||
String blank = "你看不见\u202a";
|
||||
Assert.assertTrue(StrUtil.isBlank(blank));
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,7 @@ public class JSONObjectTest {
|
||||
@Test
|
||||
public void toStringTest2() {
|
||||
String str = "{\"test\":\"关于开展2018年度“文明集体”、“文明职工”评选表彰活动的通知\"}";
|
||||
//noinspection MismatchedQueryAndUpdateOfCollection
|
||||
JSONObject json = new JSONObject(str);
|
||||
Assert.assertEquals(str, json.toString());
|
||||
}
|
||||
@ -112,6 +113,7 @@ public class JSONObjectTest {
|
||||
@Test
|
||||
public void parseStringTest2() {
|
||||
String jsonStr = "{\"file_name\":\"RMM20180127009_731.000\",\"error_data\":\"201121151350701001252500000032 18973908335 18973908335 13601893517 201711211700152017112115135420171121 6594000000010100000000000000000000000043190101701001910072 100001100 \",\"error_code\":\"F140\",\"error_info\":\"最早发送时间格式错误,该字段可以为空,当不为空时正确填写格式为“YYYYMMDDHHMISS”\",\"app_name\":\"inter-pre-check\"}";
|
||||
//noinspection MismatchedQueryAndUpdateOfCollection
|
||||
JSONObject json = new JSONObject(jsonStr);
|
||||
Assert.assertEquals("F140", json.getStr("error_code"));
|
||||
Assert.assertEquals("最早发送时间格式错误,该字段可以为空,当不为空时正确填写格式为“YYYYMMDDHHMISS”", json.getStr("error_info"));
|
||||
@ -120,6 +122,7 @@ public class JSONObjectTest {
|
||||
@Test
|
||||
public void parseStringTest3() {
|
||||
String jsonStr = "{\"test\":\"体”、“文\"}";
|
||||
//noinspection MismatchedQueryAndUpdateOfCollection
|
||||
JSONObject json = new JSONObject(jsonStr);
|
||||
Assert.assertEquals("体”、“文", json.getStr("test"));
|
||||
}
|
||||
@ -127,6 +130,7 @@ public class JSONObjectTest {
|
||||
@Test
|
||||
public void parseStringTest4() {
|
||||
String jsonStr = "{'msg':'这里还没有内容','data':{'cards':[]},'ok':0}";
|
||||
//noinspection MismatchedQueryAndUpdateOfCollection
|
||||
JSONObject json = new JSONObject(jsonStr);
|
||||
Assert.assertEquals(new Integer(0), json.getInt("ok"));
|
||||
Assert.assertEquals(new JSONArray(), json.getJSONObject("data").getJSONArray("cards"));
|
||||
@ -146,6 +150,7 @@ public class JSONObjectTest {
|
||||
public void parseStringWithSlashTest() {
|
||||
//在5.3.2之前,</div>中的/会被转义,修复此bug的单元测试
|
||||
String jsonStr = "{\"a\":\"<div>aaa</div>\"}";
|
||||
//noinspection MismatchedQueryAndUpdateOfCollection
|
||||
JSONObject json = new JSONObject(jsonStr);
|
||||
Assert.assertEquals("<div>aaa</div>", json.get("a"));
|
||||
Assert.assertEquals(jsonStr, json.toString());
|
||||
@ -454,4 +459,32 @@ public class JSONObjectTest {
|
||||
@Alias("age")
|
||||
private Integer value2;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseBeanSameNameTest(){
|
||||
final SameNameBean sameNameBean = new SameNameBean();
|
||||
final JSONObject parse = JSONUtil.parseObj(sameNameBean);
|
||||
Assert.assertEquals("123", parse.getStr("username"));
|
||||
Assert.assertEquals("abc", parse.getStr("userName"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试子Bean
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
public static class SameNameBean {
|
||||
private final String username = "123";
|
||||
private final String userName = "abc";
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user