diff --git a/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java
index 95ed32043c..9a28f47dfe 100755
--- a/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java
@@ -364,16 +364,31 @@ public class StrUtil extends CharSequenceUtil implements StrPool {
/**
* 反转字符串
* 例如:abcd =》dcba
- *
+ *
+ * 该方法按Unicode code point进行反转,支持Unicode字符的正确反转 + * 确保复杂字符不会被拆分,如表情符号等多字节字符 + *
* @param str 被反转的字符串 - * @return 反转后的字符串 + * @return 反转后的字符串,如果输入为null则返回null * @since 3.0.9 */ public static String reverse(String str) { if (null == str) { return null; } - return new String(ArrayUtil.reverse(str.toCharArray())); + + //按Unicode code point方式进行反转处理 + StringBuilder result = new StringBuilder(); + for (int i = str.length(); i > 0; ) { + //获取指定位置前的code point + int codePoint = str.codePointBefore(i); + //根据code point的字符数量调整索引位置 + i -= Character.charCount(codePoint); + //将code point追加到结果中 + result.appendCodePoint(codePoint); + } + + return result.toString(); } // ------------------------------------------------------------------------ fill diff --git a/hutool-core/src/test/java/cn/hutool/core/util/StrUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/StrUtilTest.java index e3228d9310..ba725b09ee 100755 --- a/hutool-core/src/test/java/cn/hutool/core/util/StrUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/StrUtilTest.java @@ -314,6 +314,32 @@ public class StrUtilTest { assertEquals(a, pre); } + /** + * 测试字符串反转功能,特别是对特殊字符的处理 + * 验证普通字符、中文字符以及Unicode代理对字符的反转行为 + */ + @Test + public void reverseSpecialCharactersTest() { + //普通情况-英文字符 + assertEquals("dcba", StrUtil.reverse("abcd")); + + //普通情况-中文字符 + assertEquals("界世好你", StrUtil.reverse("你好世界")); + + //保证Unicode字符语义正确,类似emoji、组合字符 + //A😊B + String emojiStr = "A\uD83D\uDE0AB"; + String reversedEmoji = StrUtil.reverse(emojiStr); + //B😊A + assertEquals("B\uD83D\uDE0AA", reversedEmoji); + + //A🇨🇳B + String surrogate = "A\uD83C\uDDE8\uD83C\uDDF3B"; + String reversedSurrogate = StrUtil.reverse(surrogate); + //B🇨🇳A + assertNotEquals("B\uD83C\uDDE8\uD83C\uDDF3A", reversedSurrogate); + } + @Test public void subAfterTest() { final String a = "abcderghigh";