使用Unicode符号作为Java标识符是一个好主意吗?

30

我有一段代码,看起来像这样:

double Δt = lastPollTime - pollTime;
double α = 1 - Math.exp(-Δt / τ);
average += α * (x - average);

仅使用Unicode字符作为Java标识符是一个多么糟糕的想法?或者这是完全可以接受的吗?

48
把英文文本翻译成中文:你是否曾经想过倒立着走路 - polygenelubricants
34
我不确定我刚刚是点了个赞还是踩了它的... - Thomas
顺便提一下,您可能会对查看由Sun的Guy L Steele等人开发的Fortress语言感兴趣。它支持广泛的Unicode运算符,甚至ASCII运算符也可以“漂亮地打印”成Unicode——请参见http://projectfortress.sun.com/Projects/Community/wiki/MathSyntaxInFortress - Cowan
3
这让我想起了APL编程语言。请告诉我您使用该语言的舒适度如何? - bart
¿ʇɹɐ ʇnoqɐ ʇɐɥʍ ʇnq 'sǝʎ - President James K. Polk
7个回答

36

出于多种原因,这是个不好的主意。

  • 很多人的键盘不支持这些字符。如果我在qwerty键盘(或任何其他没有希腊字母的键盘)上维护该代码,我将不得不一直复制和粘贴那些字符。

  • 有些人的编辑器或终端可能无法正确显示这些字符。例如,一些编辑器(不幸的是)仍然默认为某些ISO-8859(拉丁语)变体。 ASCII 之所以如此流行的主要原因是它几乎总是有效的。

  • 即使这些字符可以正常呈现,它们也可能会引起混淆。直接来自 Sun(强调是我的):

    外观相同的标识符可能是不同的。 例如,由单个字母组成的标识符 LATIN CAPITAL LETTER A(A,\u0041),LATIN SMALL LETTER A(a,\u0061),GREEK CAPITAL LETTER ALPHA(A,\u0391),CYRILLIC SMALL LETTER A(a,\u0430)和 MATHEMATICAL BOLD ITALIC SMALL A(a,\ud835 \udc82)都是不同的。

    ...

    Unicode 组合字符与分解字符不同。 例如,LATIN CAPITAL LETTER A ACUTE(Á,\u00c1)在排序时可以被认为是与 LATIN CAPITAL LETTER A(A,\u0041)紧随其后的 NON-SPACING ACUTE(´,\u0301)相同,但在标识符中它们是不同的。

    这绝非一个虚构的问题:α (U+03b1 GREEK SMALL LETTER ALPHA) 和 ⍺ (U+237a APL FUNCTIONAL SYMBOL ALPHA) 是不同的字符!

  • 无法确定哪些字符是有效的。您代码中的字符可以使用,但当我使用函数符号 ALPHA 时,我的 Java 编译器会抱怨“非法字符:\9082”。尽管在此代码中使用功能符号更为合适。除了 询问 Character.isJavaIdentifierPart() ,似乎没有一个确定的规则来确定哪些字符是可接受的。

  • 即使您可以使其编译通过,看起来不太可能所有 Java 虚拟机实现都经过了Unicode标识符的严格测试。如果这些字符仅用于方法范围内的变量,则它们应该被编译掉,但如果它们是类成员,则它们也将出现在 .class 文件中,可能会在有缺陷的 JVM 实现上破坏您的程序。


  • 进一步说,你依赖于底层平台的默认文件编码。尽管可以在Sun JVM上使用-Dfile.encoding进行控制(是的,这取决于JVM的实现...),但你真的不想依赖它。我认为这是主要的障碍。顺便说一句,很棒的答案,+1。 - BalusC
    4
    @BalusC:谢谢,但我认为你误解了。在.class文件的内部,只使用一种编码方式,类似于UTF-8。http://en.wikipedia.org/wiki/Class_%28file_format%29 就我所知,file.encoding只用于指定InputStreamReader等类的默认编码方式。 - Thomas

    9

    看起来很好,因为它使用了正确的符号,但你的团队有多少人知道这些符号的按键组合呢?

    我会使用英文表示法,只是为了更容易输入。而且其他人可能没有设置支持这些符号的字符集。


    7

    那段代码读起来还好,但是维护起来很糟糕 - 我建议使用类似这样的简单英文标识符:

    double deltaTime = lastPollTime - pollTime;
    double alpha = 1 - Math.exp(-delta....
    

    4
    如果在您的工作组中被接受,那么使用非英语标识符是完全可以接受的。这里很多答案都基于一种傲慢的假设,即每个人都使用英语编程。如今,非英语编程人员并不罕见,而且他们正在以加速的速度变得越来越普遍。既然有了一种完美的语言,为什么他们要限制自己只使用英语版本呢?
    除了盲目自大的英语思维之外,还有其他合理的使用非英语标识符的原因。例如,如果您正在编写数学软件包,并且目标用户是数学家,那么使用希腊字母是可以接受的。为什么在您的工作组中人们要打出“delta”,而不是使用大家都能理解并且可能更快地输入的“Δ”呢?几乎任何问题域都有自己的术语,有时这些术语用的不是拉丁字母表。为什么你要把所有东西都塞进ASCII里呢?

    4
    @Longpoke:请指出哪里我说过“你只懂英语所以你很菜”。(提示:这是不可能的。)甚至请指出我曾经暗示过这一点。(提示:这也是不可能的。)但是我要指出的是,那些说“不要在标识符中使用Unicode,因为这会使阅读变得困难”的人持有非常傲慢的态度,认为只有讲英语的程序员才算数。因此,“anglophone arrogance”。 - JUST MY correct OPINION
    6
    问题在于Java中的关键字是英文,例如ifwhilepublicclass等,以及运行库中的所有方法。如果使用另一种语言来命名标识符和方法,读者在阅读代码时必须不断地在两种语言之间进行思维切换。即使读者对两种语言都很熟练,这也比只有一种语言更加困难。 - Thorbjørn Ravn Andersen
    3
    @Thorbjørn:Java中的关键字是伪英语。Java中的“if”不是英语中的“if”,它是形式逻辑中的“if”,它只与英语有一点相似。同样,"while"、 "public"、 "class"等也是如此。这些不是单词,它们是符号。我们不将它们视为英语单词,而是将它们视为在Java中具有特定含义的符号(在另一种编程语言中往往具有完全不同的含义!)。因此,我们已经在两种语言之间不断地切换。通过使用我们母语的标识符,这种情况变得明确了。 - JUST MY correct OPINION
    2
    @ttmrichter,你在关键字方面可能有一定的正确性,但在运行库中使用的标识符方面则不然。几乎不可能编写任何非平凡的Java程序而不涉及运行库,其中包含大量驼峰式英文单词。是的,我说的是个人经验。到目前为止,我们尝试将丹麦语单词写入Java程序的尝试并不顺利,我得出结论是语言切换的问题。唯一的例外是没有合理的英语翻译的特定领域概念。 - Thorbjørn Ravn Andersen
    1
    问题是,我也是一个几乎母语为德语、并且有一定程度的法语能力。当阅读德国人写的代码时,切换德语和英语对我来说没有任何困难。事实上,相较于他们用德语写作,我更容易被他们在代码和注释中使用的非习惯用法的英语所干扰。因此,基于个人经验,我不得不说我仍然持不同意见。当然,这意味着我从一个以英语为母语的角度看待外国代码作者的情况。如果我是一个写代码的德国人,我不确定会有何种感受。 - JUST MY correct OPINION
    显示剩余10条评论

    2

    这是一个非常好的想法,说实话。只是现在不太容易实现。我们可以将其记录下来,留待未来参考。我很希望看到三角形、圆形、正方形等图形成为程序代码的一部分。但现在,请试着按照Crozin建议的方式重新编写它。


    1

    为什么不呢? 如果编写该代码的人可以轻松输入这些字符,那就可以接受。

    但是对于无法显示Unicode或无法输入它们的人来说,情况就会很糟糕。


    3
    任何不能显示 Unicode 的人现在都应该摆脱80年代,进入21世纪。我的意思是,即使 RSTS/E 系统的国际化(i18n)开始就已经存在了! - JUST MY correct OPINION
    1
    如果没有大量配置错误的机器和过时的软件存在,你的说法是正确的... - Thomas
    在Unix和Linux世界中,有很多人在控制台中使用vim或emacs来完成他们的工作,但不能保证他们能够看到或写入Unicode字符。 - LukeN
    2
    如果Vim和Emacs无法显示已存在近20年的标准字符,那么它们作为高效开发工具的声誉可能被严重高估了。或者,如果这是Unix系统的问题,也许Unix并不是被吹嘘为万能/终极系统。认真点,赶上21世纪吧,这里很棒。 (幸运的是,我的Linux系统似乎对21世纪的字符处理得非常好,考虑到我住的地方等因素。) - JUST MY correct OPINION

    1
    在完美的世界中,这是推荐的方法。
    不幸的是,当超出普通7位ASCII字符时(UTF-8与ISO-Latin-1不同,UTF-16等),您将遇到字符编码问题,这意味着您最终会遇到问题。当我从Windows移动到Linux时,就发生了这种情况。在转换过程中,我们的北欧语言字符被破坏了,但幸运的是只存在于字符串中。然后,我们对所有这些使用了\u编码。
    如果您可以确保您永远不会遇到这样的事情-例如,如果您的文件包含适当的BOM-那么请务必这样做。这将使您的代码更易读。 如果至少有一点怀疑,请不要这样做。
    (请注意,“使用非英语语言”是另一回事。我只是考虑使用符号代替字母)。

    那些符号是非英语语言。Delta和alpha是希腊语。那是一种语言。那不是英语。 - JUST MY correct OPINION
    1
    @ttmricher,我指的是使用您的母语中的标识符,而不是使用英文术语(例如,如果是法语,则使用Cheval而不是Horse)。这与所要求的在数学意义上使用“Δ”是不同的。 - Thorbjørn Ravn Andersen

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接