1. 概述

Java 21 在 java.lang.Character 类中新增了一系列方法,显著提升了 Emoji 处理能力。这些方法能轻松判断字符是否为 Emoji,并检查其属性特征。

本文将深入探讨这些新增方法,并解析 Java 21 中 Emoji 处理的核心概念。

2. Character API 更新

Java 21 在 java.lang.Character 类中引入了六个与 Emoji 处理相关的新方法。所有新方法均为静态方法,接收表示字符 Unicode 码点的 int 参数,返回 boolean

Unicode 码点是 Unicode 标准中为每个字符分配的唯一数值,用于跨平台和语言表示特定字符。例如字母 "A" 的码点为 U+0041(十六进制形式 0x0041)。

Unicode 联盟(非营利组织)维护 Unicode 标准,并提供完整的 Emoji 列表及其对应码点

下面逐一解析这些新增的 Emoji 相关方法:

2.1. isEmoji()

isEmoji(int codePoint) 是最基础的 Emoji 检测方法。接收字符的 Unicode 码点,返回布尔值表示该字符是否为 Emoji

使用示例:

String messageWithEmoji = "Hello Java 21! 😄";
String messageWithoutEmoji = "Hello Java!";

assertTrue(messageWithEmoji.codePoints().anyMatch(Character::isEmoji));
assertFalse(messageWithoutEmoji.codePoints().anyMatch(Character::isEmoji));

2.2. isEmojiPresentation()

isEmojiPresentation(int codePoint) 方法判断字符是否应以 Emoji 形式渲染。某些字符(如数字 0-9 或货币符号 $/€)可根据上下文渲染为 Emoji 或文本形式。

代码示例:

String emojiPresentationMessage = "Hello Java 21! 🔥😄";
String nonEmojiPresentationMessage = "Hello Java 21!";

assertTrue(emojiPresentationMessage.codePoints().anyMatch(Character::isEmojiPresentation));
assertFalse(nonEmojiPresentationMessage.codePoints().anyMatch(Character::isEmojiPresentation));

2.3. isEmojiModifier()

isEmojiModifier(int codePoint) 方法检测字符是否为 Emoji 修饰符。**Emoji 修饰符可改变现有 Emoji 的外观,例如应用肤色变化**。

使用示例:

assertTrue(Character.isEmojiModifier(0x1F3FB)); // 浅肤色
assertTrue(Character.isEmojiModifier(0x1F3FD)); // 中等肤色
assertTrue(Character.isEmojiModifier(0x1F3FF)); // 深肤色

⚠️ 测试中直接使用十六进制码点(如 0x1F3FB),因为 Emoji 修饰符通常不独立显示,缺乏视觉区分度。

2.4. isEmojiModifierBase()

isEmojiModifierBase(int codePoint) 方法判断字符是否可被 Emoji 修饰符修改。此方法用于识别支持修饰的 Emoji(并非所有 Emoji 都支持)。

示例说明:

assertTrue(Character.isEmojiModifierBase(Character.codePointAt("👍", 0)));
assertTrue(Character.isEmojiModifierBase(Character.codePointAt("👶", 0)));
    
assertFalse(Character.isEmojiModifierBase(Character.codePointAt("🍕", 0)));

✅ 竖拇 Emoji "👍" 和婴儿 Emoji "👶" 是有效的修饰基础,可通过肤色变化表达多样性。

❌ 披萨 Emoji "🍕" 不是修饰基础,它是表示物体的独立 Emoji,无法修改外观。

2.5. isEmojiComponent()

isEmojiComponent(int codePoint) 方法检测字符是否可作为组件创建新 Emoji。这些字符通常与其他字符组合形成新 Emoji,而非独立显示。

例如,**零宽连接符(ZWJ)是不可见字符,指示渲染系统将相邻字符显示为单个 Emoji**。通过组合男人 "👨"(0x1F468)和火箭 "🚀"(0x1F680)并使用 ZWJ(0x200D),可创建宇航员 Emoji "👨‍🚀"。可通过Unicode 码点转换工具验证输入:0x1F4680x200D0x1F680

肤色字符也是 Emoji 组件。将深肤色字符(0x1F3FF)与挥手 Emoji "👋"(0x1F44B)组合,可创建深肤色挥手 "👋🏿"(0x1F44B0x1F3FF)。由于是修改现有 Emoji 外观而非创建新 Emoji,肤色变化无需使用 ZWJ。

使用示例:

assertTrue(Character.isEmojiComponent(0x200D)); // 零宽连接符
assertTrue(Character.isEmojiComponent(0x1F3FD)); // 中等肤色

2.6. isExtendedPictographic()

isExtendedPictographic(int codePoint) 方法检测字符是否属于更广泛的象形符号类别,包含传统 Emoji 及其他特殊渲染符号。

物体、动物等图形符号具有扩展象形属性。它们虽不总是被视为标准 Emoji,但需作为 Emoji 集合的一部分识别处理以确保正确显示。

使用示例:

assertTrue(Character.isExtendedPictographic(Character.codePointAt("☀️", 0)));  // 太阳
assertTrue(Character.isExtendedPictographic(Character.codePointAt("✔️", 0)));  // 对勾

⚠️ 上述码点传入 isEmojiPresentation() 会返回 false,因为它们属于扩展象形类别但不具备 Emoji 展示属性。

3. 正则表达式中的 Emoji 支持

除新增方法外,Java 21 还在正则表达式中增加了 Emoji 支持。现在可使用 \p{IsXXXX} 构造基于 Emoji 属性匹配字符。

示例:在字符串中搜索任意 Emoji 字符:

String messageWithEmoji = "Hello Java 21! 😄";
Matcher isEmojiMatcher = Pattern.compile("\\p{IsEmoji}").matcher(messageWithEmoji);
    
assertTrue(isEmojiMatcher.find());

String messageWithoutEmoji = "Hello Java!";
isEmojiMatcher = Pattern.compile("\\p{IsEmoji}").matcher(messageWithoutEmoji);
    
assertFalse(isEmojiMatcher.find());

类似地,可在正则表达式中使用其他 Emoji 构造:

  • IsEmoji_Presentation
  • IsEmoji_Modifier
  • IsEmoji_Modifier_Base
  • IsEmoji_Component
  • IsExtended_Pictographic

⚠️ 正则表达式属性构造使用蛇形命名法(snake_case),与 Character 类中静态方法的驼峰命名法(lowerCamelCase)不同。

这些正则表达式构造为搜索和操作字符串中的 Emoji 提供了简洁高效的方式。

4. 总结

本文详细解析了 Java 21 中 Character 类新增的 Emoji 处理方法。通过实际示例演示了这些静态方法的行为特性。

同时探讨了正则表达式新增的 Emoji 支持,展示了如何使用 Pattern 类搜索 Emoji 字符及其属性。

这些新特性在构建聊天应用、社交媒体平台或其他使用 Emoji 的应用时将大显身手。

本文所有代码示例可在GitHub获取。


原始标题:Java Improved Emoji Support | Baeldung