如何将任意字符串转换为Java标识符?

时间:2011-09-16 06:08:47

标签: java string code-generation identifier

我需要转换任意字符串:

  • 带空格的字符串
  • 100stringsstartswithnumber
  • 字符串€与%的特别†字符/ \!
  • [空字符串]

到有效的Java标识符:

  • string_with_spaces
  • _100stringsstartswithnumber
  • string_with_special_characters ___
  • _

此任务是否有现有工具?

有了这么多Java源代码重构/生成框架,人们会认为这应该是非常常见的任务。

4 个答案:

答案 0 :(得分:11)

这个简单的方法会将任何输入字符串转换为有效的java标识符:

public static String getIdentifier(String str) {
    try {
        return Arrays.toString(str.getBytes("UTF-8")).replaceAll("\\D+", "_");
    } catch (UnsupportedEncodingException e) {
        // UTF-8 is always supported, but this catch is required by compiler
        return null;
    }
}

示例:

"%^&*\n()" --> "_37_94_38_42_10_56_94_40_41_"

任何输入字符都可以使用 - 外语字符,换行符,任何东西!
另外,这个算法是:

  • 再现的
  • unique - 即如果str1.equals(str2)
  • 总是会产生相同的结果
  • 可逆

感谢UTF-8提出public static String getIdentifier(String str) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < str.length(); i++) { if ((i == 0 && Character.isJavaIdentifierStart(str.charAt(i))) || (i > 0 && Character.isJavaIdentifierPart(str.charAt(i)))) sb.append(str.charAt(i)); else sb.append((int)str.charAt(i)); } return sb.toString(); } 建议


如果冲突正常(两个输入字符串可能产生相同的结果),此代码产生可读输出:

{{1}}

它保留有效标识符的字符,仅将那些无效的字符转换为它们的十进制等值。

答案 1 :(得分:3)

我不知道用于此目的的工具,但可以使用Character类轻松创建。

您知道字符串€with_special_characters ___是合法的java标识符吗?

public class Conv {
    public static void main(String[] args) {
        String[] idents = { "string with spaces", "100stringsstartswithnumber",
                "string€with%special†characters/\\!", "" };
        for (String ident : idents) {
            System.out.println(convert(ident));
        }
    }

    private static String convert(String ident) {
        if (ident.length() == 0) {
            return "_";
        }
        CharacterIterator ci = new StringCharacterIterator(ident);
        StringBuilder sb = new StringBuilder();
        for (char c = ci.first(); c != CharacterIterator.DONE; c = ci.next()) {
            if (c == ' ')
                c = '_';
            if (sb.length() == 0) {
                if (Character.isJavaIdentifierStart(c)) {
                    sb.append(c);
                    continue;
                } else
                    sb.append('_');
            }
            if (Character.isJavaIdentifierPart(c)) {
                sb.append(c);
            } else {
                sb.append('_');
            }
        };
        return sb.toString();
    }
}

打印

string_with_spaces
_100stringsstartswithnumber
string€with_special_characters___
_

答案 2 :(得分:1)

如果您为自动生成的代码执行此操作(即,不要太在意可读性),我最喜欢的一个就是Base64它。没有必要让语言律师知道哪些字符在编码中有效,这是“保护”任意字节数据的一种非常常见的方式。

答案 3 :(得分:1)

  

有了这么多Java源代码重构/生成框架,人们会认为这应该是非常常见的任务。

实际上并非如此。

  • 代码重构框架将从现有的有效java标识符开始,通过将它们与一些其他字符连接起来,可以生成新的标识符,以用于消除歧义。

  • 典型的代码生成框架将从受限字符集中的“名称”开始。它不必处理任意字符。


我认为转换器的目的是生成类似于输入字符串的标识符(如果可能的话)。如果是这种情况,我会按原样映射所有合法标识符字符进行转换,并用“$ xxxx”替换非法标识符字符,其中“xxxx”是Java 16位字符的4位十六进制编码。

您的方案也有效,但用'_'替换所有非法字符更有可能导致标识符冲突;即两个输入字符串映射到相同标识符的位置。

这是代码直截了当的,所以我会留给你做。