This commit is contained in:
Looly 2023-04-15 09:12:37 +08:00
parent 04aea46294
commit 0f9000adcb
10 changed files with 155 additions and 39 deletions

View File

@ -156,7 +156,8 @@ public class BeanDesc implements Serializable {
PropDesc prop; PropDesc prop;
for (final Field field : FieldUtil.getFields(this.beanClass)) { for (final Field field : FieldUtil.getFields(this.beanClass)) {
// 排除静态属性和对象子类 // 排除静态属性和对象子类
if (!ModifierUtil.isStatic(field) && !FieldUtil.isOuterClassField(field)) { if (!ModifierUtil.isStatic(field) &&
!FieldUtil.isOuterClassField(field)) {
prop = createProp(field, gettersAndSetters); prop = createProp(field, gettersAndSetters);
// 只有不存在时才放入防止父类属性覆盖子类属性 // 只有不存在时才放入防止父类属性覆盖子类属性
this.propMap.putIfAbsent(prop.getFieldName(), prop); this.propMap.putIfAbsent(prop.getFieldName(), prop);

View File

@ -10,7 +10,7 @@
* See the Mulan PSL v2 for more details. * See the Mulan PSL v2 for more details.
*/ */
package org.dromara.hutool.core.io; package org.dromara.hutool.core.io.buffer;
import org.dromara.hutool.core.text.StrUtil; import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.ByteUtil; import org.dromara.hutool.core.util.ByteUtil;
@ -23,7 +23,7 @@ import java.nio.charset.Charset;
import java.util.Arrays; import java.util.Arrays;
/** /**
* {@link ByteBuffer} 工具类<br> * {@link ByteBuffer} {@link CharBuffer}工具类<br>
* 此工具来自于 t-io 项目以及其它项目的相关部分收集<br> * 此工具来自于 t-io 项目以及其它项目的相关部分收集<br>
* ByteBuffer的相关介绍见https://www.cnblogs.com/ruber/p/6857159.html * ByteBuffer的相关介绍见https://www.cnblogs.com/ruber/p/6857159.html
* *

View File

@ -10,7 +10,7 @@
* See the Mulan PSL v2 for more details. * See the Mulan PSL v2 for more details.
*/ */
package org.dromara.hutool.core.io; package org.dromara.hutool.core.io.buffer;
/** /**
* 代码移植自<a href="https://github.com/biezhi/blade">blade</a><br> * 代码移植自<a href="https://github.com/biezhi/blade">blade</a><br>
@ -51,12 +51,20 @@ public class FastByteBuffer {
*/ */
private final int minChunkLen; private final int minChunkLen;
/**
* 构造
*/
public FastByteBuffer() { public FastByteBuffer() {
this(1024); this(1024);
} }
/**
* 构造
*
* @param size 一个缓冲区的最小字节数
*/
public FastByteBuffer(int size) { public FastByteBuffer(int size) {
if(size <= 0){ if (size <= 0) {
size = 1024; size = 1024;
} }
this.minChunkLen = Math.abs(size); this.minChunkLen = Math.abs(size);
@ -90,8 +98,8 @@ public class FastByteBuffer {
* 向快速缓冲加入数据 * 向快速缓冲加入数据
* *
* @param array 数据 * @param array 数据
* @param off 偏移量 * @param off 偏移量
* @param len 字节数 * @param len 字节数
* @return 快速缓冲自身 @see FastByteBuffer * @return 快速缓冲自身 @see FastByteBuffer
*/ */
public FastByteBuffer append(final byte[] array, final int off, final int len) { public FastByteBuffer append(final byte[] array, final int off, final int len) {
@ -134,7 +142,6 @@ public class FastByteBuffer {
* 向快速缓冲加入数据 * 向快速缓冲加入数据
* *
* @param array 数据 * @param array 数据
*
* @return 快速缓冲自身 @see FastByteBuffer * @return 快速缓冲自身 @see FastByteBuffer
*/ */
public FastByteBuffer append(final byte[] array) { public FastByteBuffer append(final byte[] array) {
@ -176,10 +183,20 @@ public class FastByteBuffer {
return this; return this;
} }
/**
* 长度
*
* @return 长度
*/
public int size() { public int size() {
return size; return size;
} }
/**
* 是否为空
*
* @return 是否为空
*/
public boolean isEmpty() { public boolean isEmpty() {
return size == 0; return size == 0;
} }
@ -193,6 +210,11 @@ public class FastByteBuffer {
return currentBufferIndex; return currentBufferIndex;
} }
/**
* 获取当前缓冲偏移量
*
* @return 当前缓冲偏移量
*/
public int offset() { public int offset() {
return offset; return offset;
} }
@ -207,6 +229,9 @@ public class FastByteBuffer {
return buffers[index]; return buffers[index];
} }
/**
* 复位缓冲
*/
public void reset() { public void reset() {
size = 0; size = 0;
offset = 0; offset = 0;
@ -243,7 +268,7 @@ public class FastByteBuffer {
* 返回快速缓冲中的数据 * 返回快速缓冲中的数据
* *
* @param start 逻辑起始位置 * @param start 逻辑起始位置
* @param len 逻辑字节长 * @param len 逻辑字节长
* @return 快速缓冲中的数据 * @return 快速缓冲中的数据
*/ */
public byte[] toArray(int start, final int len) { public byte[] toArray(int start, final int len) {

View File

@ -0,0 +1,18 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* {@link java.nio.Buffer}相关工具封装
*
* @author looly
*/
package org.dromara.hutool.core.io.buffer;

View File

@ -12,7 +12,7 @@
package org.dromara.hutool.core.io.stream; package org.dromara.hutool.core.io.stream;
import org.dromara.hutool.core.io.FastByteBuffer; import org.dromara.hutool.core.io.buffer.FastByteBuffer;
import org.dromara.hutool.core.io.IORuntimeException; import org.dromara.hutool.core.io.IORuntimeException;
import org.dromara.hutool.core.util.CharsetUtil; import org.dromara.hutool.core.util.CharsetUtil;
import org.dromara.hutool.core.util.ObjUtil; import org.dromara.hutool.core.util.ObjUtil;
@ -62,6 +62,11 @@ public class FastByteArrayOutputStream extends OutputStream {
buffer.append((byte) b); buffer.append((byte) b);
} }
/**
* 长度
*
* @return 长度
*/
public int size() { public int size() {
return buffer.size(); return buffer.size();
} }
@ -74,18 +79,22 @@ public class FastByteArrayOutputStream extends OutputStream {
// nop // nop
} }
/**
* 复位
*/
public void reset() { public void reset() {
buffer.reset(); buffer.reset();
} }
/** /**
* 写出 * 写出
*
* @param out 输出流 * @param out 输出流
* @throws IORuntimeException IO异常 * @throws IORuntimeException IO异常
*/ */
public void writeTo(final OutputStream out) throws IORuntimeException { public void writeTo(final OutputStream out) throws IORuntimeException {
final int index = buffer.index(); final int index = buffer.index();
if(index < 0){ if (index < 0) {
// 无数据写出 // 无数据写出
return; return;
} }
@ -104,6 +113,7 @@ public class FastByteArrayOutputStream extends OutputStream {
/** /**
* 转为Byte数组 * 转为Byte数组
*
* @return Byte数组 * @return Byte数组
*/ */
public byte[] toByteArray() { public byte[] toByteArray() {
@ -117,12 +127,13 @@ public class FastByteArrayOutputStream extends OutputStream {
/** /**
* 转为字符串 * 转为字符串
*
* @param charset 编码,null表示默认编码 * @param charset 编码,null表示默认编码
* @return 字符串 * @return 字符串
*/ */
public String toString(final Charset charset) { public String toString(final Charset charset) {
return new String(toByteArray(), return new String(toByteArray(),
ObjUtil.defaultIfNull(charset, CharsetUtil::defaultCharset)); ObjUtil.defaultIfNull(charset, CharsetUtil::defaultCharset));
} }
} }

View File

@ -24,6 +24,7 @@ import org.dromara.hutool.core.lang.Singleton;
import org.dromara.hutool.core.map.WeakConcurrentMap; import org.dromara.hutool.core.map.WeakConcurrentMap;
import org.dromara.hutool.core.text.StrUtil; import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.array.ArrayUtil; import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.core.util.BooleanUtil;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
@ -215,10 +216,10 @@ public class MethodUtil {
if (ArrayUtil.isNotEmpty(methods)) { if (ArrayUtil.isNotEmpty(methods)) {
for (final Method method : methods) { for (final Method method : methods) {
if (StrUtil.equals(methodName, method.getName(), ignoreCase) if (StrUtil.equals(methodName, method.getName(), ignoreCase)
&& ClassUtil.isAllAssignableFrom(method.getParameterTypes(), paramTypes) && ClassUtil.isAllAssignableFrom(method.getParameterTypes(), paramTypes)
//排除桥接方法pr#1965@Github //排除桥接方法pr#1965@Github
//排除协变桥接方法pr#1965@Github //排除协变桥接方法pr#1965@Github
&& (res == null || res.getReturnType().isAssignableFrom(method.getReturnType()))) { && (res == null || res.getReturnType().isAssignableFrom(method.getReturnType()))) {
res = method; res = method;
} }
} }
@ -284,8 +285,8 @@ public class MethodUtil {
if (ArrayUtil.isNotEmpty(methods)) { if (ArrayUtil.isNotEmpty(methods)) {
for (final Method method : methods) { for (final Method method : methods) {
if (StrUtil.equals(methodName, method.getName(), ignoreCase) if (StrUtil.equals(methodName, method.getName(), ignoreCase)
//排除协变桥接方法pr#1965@Github //排除协变桥接方法pr#1965@Github
&& (res == null || res.getReturnType().isAssignableFrom(method.getReturnType()))) { && (res == null || res.getReturnType().isAssignableFrom(method.getReturnType()))) {
res = method; res = method;
} }
} }
@ -335,7 +336,7 @@ public class MethodUtil {
public static Method[] getMethods(final Class<?> beanClass) throws SecurityException { public static Method[] getMethods(final Class<?> beanClass) throws SecurityException {
Assert.notNull(beanClass); Assert.notNull(beanClass);
return METHODS_CACHE.computeIfAbsent(beanClass, return METHODS_CACHE.computeIfAbsent(beanClass,
(key) -> getMethodsDirectly(beanClass, true, true)); (key) -> getMethodsDirectly(beanClass, true, true));
} }
/** /**
@ -348,7 +349,7 @@ public class MethodUtil {
public static Method[] getDeclaredMethods(final Class<?> beanClass) throws SecurityException { public static Method[] getDeclaredMethods(final Class<?> beanClass) throws SecurityException {
Assert.notNull(beanClass); Assert.notNull(beanClass);
return DECLARED_METHODS_CACHE.computeIfAbsent(beanClass, return DECLARED_METHODS_CACHE.computeIfAbsent(beanClass,
key -> getMethodsDirectly(beanClass, false, Objects.equals(Object.class, beanClass))); key -> getMethodsDirectly(beanClass, false, Objects.equals(Object.class, beanClass)));
} }
/** /**
@ -398,8 +399,8 @@ public class MethodUtil {
*/ */
public static boolean isEqualsMethod(final Method method) { public static boolean isEqualsMethod(final Method method) {
if (method == null || if (method == null ||
1 != method.getParameterCount() || 1 != method.getParameterCount() ||
!"equals".equals(method.getName())) { !"equals".equals(method.getName())) {
return false; return false;
} }
return (method.getParameterTypes()[0] == Object.class); return (method.getParameterTypes()[0] == Object.class);
@ -413,8 +414,8 @@ public class MethodUtil {
*/ */
public static boolean isHashCodeMethod(final Method method) { public static boolean isHashCodeMethod(final Method method) {
return method != null// return method != null//
&& "hashCode".equals(method.getName())// && "hashCode".equals(method.getName())//
&& isEmptyParam(method); && isEmptyParam(method);
} }
/** /**
@ -425,8 +426,8 @@ public class MethodUtil {
*/ */
public static boolean isToStringMethod(final Method method) { public static boolean isToStringMethod(final Method method) {
return method != null// return method != null//
&& "toString".equals(method.getName())// && "toString".equals(method.getName())//
&& isEmptyParam(method); && isEmptyParam(method);
} }
/** /**
@ -471,32 +472,91 @@ public class MethodUtil {
* @since 5.7.20 * @since 5.7.20
*/ */
public static boolean isGetterOrSetter(final Method method, final boolean ignoreCase) { public static boolean isGetterOrSetter(final Method method, final boolean ignoreCase) {
// 参数个数必须为1
final int parameterCount = method.getParameterCount();
switch (parameterCount){
case 0:
return isGetter(method, ignoreCase);
case 1:
return isSetter(method, ignoreCase);
default:
return false;
}
}
/**
* 检查给定方法是否为Setter方法规则为<br>
* <ul>
* <li>方法参数必须为1个</li>
* <li>判断是否以set开头</li>
* </ul>
*
* @param method 方法
* @param ignoreCase 是否忽略方法名的大小写
* @return 是否为Setter方法
*/
public static boolean isSetter(final Method method, final boolean ignoreCase) {
if (null == method) {
return false;
}
// 参数个数必须为1
final int parameterCount = method.getParameterCount();
if (1 != parameterCount) {
return false;
}
String name = method.getName();
// 跳过set这类特殊方法
if ("set".equals(name)) {
return false;
}
if (ignoreCase) {
name = name.toLowerCase();
}
return name.startsWith("set");
}
/**
* 检查给定方法是否为Getter方法规则为<br>
* <ul>
* <li>方法参数必须为0个</li>
* <li>方法名称不能是getClass</li>
* <li>"is"开头返回必须为boolean或Boolean</li>
* <li>是否以get</li>
* </ul>
*
* @param method 方法
* @param ignoreCase 是否忽略方法名的大小写
* @return 是否为Getter方法
*/
public static boolean isGetter(final Method method, final boolean ignoreCase) {
if (null == method) { if (null == method) {
return false; return false;
} }
// 参数个数必须为0或1 // 参数个数必须为0或1
final int parameterCount = method.getParameterCount(); final int parameterCount = method.getParameterCount();
if (parameterCount > 1) { if (0 != parameterCount) {
return false; return false;
} }
String name = method.getName(); String name = method.getName();
// 跳过getClass这个特殊方法 // 跳过getClassgetis这类特殊方法
if ("getClass".equals(name)) { if ("getClass".equals(name) || "get".equals(name) || "is".equals(name)) {
return false; return false;
} }
if (ignoreCase) { if (ignoreCase) {
name = name.toLowerCase(); name = name.toLowerCase();
} }
switch (parameterCount) {
case 0: if (name.startsWith("is")) {
return name.startsWith("get") || name.startsWith("is"); // 判断返回值是否为Boolean
case 1: return BooleanUtil.isBoolean(method.getReturnType());
return name.startsWith("set");
default:
return false;
} }
return name.startsWith("get");
} }
// --------------------------------------------------------------------------------------------------------- invoke // --------------------------------------------------------------------------------------------------------- invoke

View File

@ -2,6 +2,7 @@ package org.dromara.hutool.core.io;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.dromara.hutool.core.io.buffer.BufferUtil;
import org.dromara.hutool.core.text.StrUtil; import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.CharsetUtil; import org.dromara.hutool.core.util.CharsetUtil;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;

View File

@ -1,7 +1,7 @@
package org.dromara.hutool.socket.aio; package org.dromara.hutool.socket.aio;
import org.dromara.hutool.core.date.DateUtil; import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.io.BufferUtil; import org.dromara.hutool.core.io.buffer.BufferUtil;
import org.dromara.hutool.core.lang.Console; import org.dromara.hutool.core.lang.Console;
import org.dromara.hutool.core.text.StrUtil; import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.log.StaticLog; import org.dromara.hutool.log.StaticLog;

View File

@ -1,6 +1,6 @@
package org.dromara.hutool.socket.nio; package org.dromara.hutool.socket.nio;
import org.dromara.hutool.core.io.BufferUtil; import org.dromara.hutool.core.io.buffer.BufferUtil;
import org.dromara.hutool.core.lang.Console; import org.dromara.hutool.core.lang.Console;
import org.dromara.hutool.core.text.StrUtil; import org.dromara.hutool.core.text.StrUtil;
import lombok.SneakyThrows; import lombok.SneakyThrows;

View File

@ -1,6 +1,6 @@
package org.dromara.hutool.socket.nio; package org.dromara.hutool.socket.nio;
import org.dromara.hutool.core.io.BufferUtil; import org.dromara.hutool.core.io.buffer.BufferUtil;
import org.dromara.hutool.core.io.IORuntimeException; import org.dromara.hutool.core.io.IORuntimeException;
import org.dromara.hutool.core.io.IoUtil; import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.lang.Console; import org.dromara.hutool.core.lang.Console;