以下代码生成输出"hello world!"(不,真的,试试看)。
1 2 3 4 5
| public static void main (String... args) {
// The comment below is not a typo.
// \u000d System.out.println("Hello World!");
} |
这样做的原因是Java编译器将Unicode字符EDCOX1(0)作为新行解析并转换成:
1 2 3 4 5 6
| public static void main (String... args) {
// The comment below is not a typo.
//
System. out. println("Hello World!");
} |
从而导致"执行"注释。
既然这可以用来"隐藏"恶意代码或者恶意程序员能想到的任何东西,为什么在注释中允许这样做?
为什么Java规范允许这样做?
- "为什么允许这样做"在我看来太过基于观点。语言设计者做出了决定,还有什么需要知道的?除非你找到作出决定的人的陈述,我们只能推测。
- 虽然很奇怪,但我不认为这是真正的问题。普通用户不会知道隐藏在注释中的代码和普通代码之间的区别,所以对他们来说这并不重要。然后,它可能是一个团队成员向其他成员隐藏代码,但是当开发人员看到这样一个奇怪的注释时,会做出反应,或者删除它,或者进行调查。如果这是通过并投入使用,一个风投会告诉你是谁做的,所以有人会被抓住。
- \u000d表示ascii 0x0D、
、New Line。
- 一件有趣的事情是,至少Op的IDE显然弄错了,并显示了不正确的突出显示,
- @肖恩,这是有疑问的解释。OP询问为什么在评论部分它也被翻译成
。
- 可能相关:stackoverflow.com/questions/4448180/…
- @托布:是的,权威的答案只能来自设计师。但是,可能有一些信息说明为什么要这样做(兼容性、工具限制等),所以这是可以回答的。
- @芭丝谢芭,这不适合一个好问题,也不适合按照SO标准回答一个问题。如果你仔细看,第一次投票结束是由Tjcrowder完成的,他有360349个代表。
- '因为也允许换行符…我用C++和C语言进行了测试,这些语言在读/读之后跳过了线,但是Java似乎解析了行并将代码解释为换行字符。
- @ ToBB,但Java设计者正在访问,所以可以通过其中一个来获得答案。此外,他们可能存在已经回答这个问题的资源。
- 我不确定,但我怀疑这只是处理评论中的单进程字符的一般决策的副作用。可能允许使用外语或数学希腊符号进行代码注释。就我个人而言,我会避免…(javadoc可能是一个例外,但是我不需要这个特性,因为HTML对特殊字符有自己的支持)。
- stackoverflow.com/questions/386187/…有趣的例子
- Unicode转义在任何地方都允许,并且总是在分析其他内容之前进行分析。其目的是任何源文件都可以转换为仅包含ASCII字符的等效文件。
- 相关:stackoverflow.com/q/13116648/319403
- @DHKE:这在Eclipse中也显示为注释,所以您知道任何不显示为注释的IDE吗?
- @在Unicode转义换行后,ThomasNetBeans(至少在8.0.2中)终止了注释,将println()显示为代码。它还显示了与stackoverflow.com/questions/4448180/…中转义注释开始代码的编译器相同的行为。
- 这也意味着注释中无效的unicode转义会导致编译错误(例如继续执行\users的Windows路径),这可能会很烦人。
- @DHKE操作人员没有提到他/她的IDE如何显示该代码。唯一突出的是,我们可以从问题文本中看出,这里的Java代码高亮显示了它的错误。
- 您所显示的是IDE中的一个bug。这是完全有效的代码。IDE没有将其显示为代码就是错误。IDE需要停止假设编译器不认识Unicode。
- @好奇的兔子,是什么让你得出结论说这是一个昆虫在手术室里?(你怎么知道OP正在使用一个IDE?)
- 简单的答案是,根据语言规则,代码根本不在注释中,因此问题的形式不正确。
- @托马斯EclipseLuna在单码马车返回后终止了评论。它的默认行为是在保存文档时"解析"Unicode字符,因此在Unicode回车后在注释中写入的任何代码实际上都将显示在注释行之外。
- @哎呀,也许用IDE这个词是自以为是的。错误出现在编辑器/ide/或用户对"line"与"statement"的感知中。通过使用语法感知编辑器,用户对活动语句的感知可以大大增强。如果语法感知编辑器不能正确处理支持语言语法的某个方面,那么该工具就出错了,这是一个bug。
- 所以,语法高亮,当然,不知道它处理的是Java。这是一个"各行各业的杰克",它一定会绊倒在边缘案件。
- @SpringLearner有大量这样的代表,并不意味着他们有一个权威的观点,每个人都应该遵循。虽然这个问题的措词可能会改变("为什么"很固执己见),但我认为这是一个很好的话题,我很高兴它被提出来。
- @托布-一个相当聪明的作恶者会确保它看起来像评论的一部分。不应该很难让它看起来无辜。
- 假设它不是编译器中的一个bug,我会把它称为规范中的一个严重的、令人震惊的缺陷。恶意员工确实存在,如果没有语言的帮助,他们已经够危险了。
- 你可以用这个技巧来评论整个班级,它仍然会运行!
- 我觉得题目不对。在这种情况下,字符u000d将终止注释,因此代码根本不在注释中。这就像要求编译器在注释结尾处解析换行符而不是永远进行一样荒谬。最后,这一缺陷源于使用其他非基于行的语言将注释行作为基础的固有缺陷。
- 这就是问题的全部前提,不是吗?
- 无耻的插头:你可以在:obfuscat.ion.land玩这个。
- \u000d是回车;\u000a是换行符。他们中的任何一个都完成了//的评论。
- 爪哇中Unicode换行符(U000 0D)的可能副本
- 我投票结束这个问题,因为这个问题是关于语言设计的,而不是编程本身。
- 我投票决定将此问题作为非主题结束,因为无法重新创建错误。代码不是注释,但是它是操作的IDE,但是这是IDE中的一个错误,与是否可以在注释中执行代码几乎没有关系。
- 为什么编译器接受字符串/字符文本之外的u-序列?嗯,乍一看,这似乎是个好主意。事后看来,这不是个好主意,但为时已晚。(注:在评论中有很多提到"ide",但这个问题与任何"ide"都无关。)
- @ LorinczyZsigmond允许UTF-16代码单元逃逸的目的是在源文件中支持所有有效的Java标识符(特别是类名),而字符编码不支持。
Unicode解码发生在任何其他词汇翻译之前。这样做的主要好处是,在ASCII和任何其他编码之间来回切换都很简单。你甚至不需要知道评论从哪里开始和结束!
如JLS第3.3节所述,这允许任何基于ASCII的工具处理源文件:
[...] The Java programming language specifies a standard way of transforming a program written in Unicode into ASCII that changes a program into a form that can be processed by ASCII-based tools. [...]
这为平台独立性(支持字符集的独立性)提供了基本保证,这一直是Java平台的一个关键目标。
在用非拉丁语编写代码文档时,能够在文件中的任何位置编写任何Unicode字符是一个很好的特性,在注释中尤其重要。它能以如此微妙的方式干扰语义,这只是一个(不幸的)副作用。
在这个主题上有很多问题,Joshua Bloch和Neal Gafter的Java难题包括以下变型:
Is this a legal Java program? If so, what does it print?
1 2 3 4 5 6 7 8 9 10 11
| \u0070\u0075\u0062\u006c\u0069\u0063\u0020\u0020\u0020\u0020
\u0063\u006c\u0061\u0073\u0073\u0020\u0055\u0067\u006c\u0079
\u007b\u0070\u0075\u0062\u006c\u0069\u0063\u0020\u0020\u0020
\u0020\u0020\u0020\u0020\u0073\u0074\u0061\u0074\u0069\u0063
\u0076\u006f\u0069\u0064\u0020\u006d\u0061\u0069\u006e\u0028
\u0053\u0074\u0072\u0069\u006e\u0067\u005b\u005d\u0020\u0020
\u0020\u0020\u0020\u0020\u0061\u0072\u0067\u0073\u0029\u007b
\u0053\u0079\u0073\u0074\u0065\u006d\u002e\u006f\u0075\u0074
\u002e\u0070\u0072\u0069\u006e\u0074\u006c\u006e\u0028\u0020
\u0022\u0048\u0065\u006c\u006c\u006f\u0020\u0077\u0022\u002b
\u0022\u006f\u0072\u006c\u0064\u0022\u0029\u003b\u007d\u007d |
(这是一个简单的"你好世界"节目。)
在解题中,他们指出了以下几点:
More seriously, this puzzle serves to reinforce the lessons of the previous three: Unicode escapes are essential when you need to insert characters that can’t be represented in any other way into your program. Avoid them in all other cases.
来源:Java:在注释中执行代码?!
- 简而言之,Java有意允许它:"bug"在OP的IDE中?
- @芭丝谢芭:更多的是在人们的头脑里。人们并不试图理解Java解析是如何工作的,所以有时候它们会以错误的方式显示代码。在上面的例子中,注释应该以\u000d结尾,后面的部分应该突出显示代码。
- 另一个常见的错误是在代码中粘贴Windows路径,如// C:\user\...,这会导致编译错误,因为\user不是有效的unicode转义序列。
- 我了解Unicode字符的介绍,但不太了解为什么在注释中允许使用它?
- 在Eclipse中,\u000d后面的代码部分突出显示。按ctrl+shift+f后,字符将替换为新行,其余行将换行。
- 所以…这与编译器如何解析源代码文件有关?。当我们使用块注释而不是单行注释时,无法复制此问题。
- @注册,有许多功能的语言没有意义,与其他功能的语言。在这种情况下,语言设计者将Unicode转义处理放在解析器之前,能够在共生体中使用Unicode转义只是一个(可能是不幸的)副作用。
- 虽然我同意@aioobe的回答,即源代码是有效的,问题在IDE中(以及stackoverflow上的源代码highlighter),但请注意,代码还有另一个"问题"。作为unicode转义序列输入的CR字符被解释为新行的正确开头,但行号不递增。
- @Umakanth,//的评论被跳过,一直跳到下一个新行字符。\u000d被解释为一个新行字符。
- @首先,如果我正确理解了答案,你也应该能够用块注释来重现这个问题。\u002A/应该结束评论。
- @泰梅尔哇,江户十一〔6〕真的很邪恶,日食完全无法解析它。把代码放在/*\u002A/和/\u002a*/之间,它作为注释完全隐藏。发现这个是错误3533
- 请注意,如果语言规范禁止使用\u符号来表示任何可以用ASCII表示的内容,则可以完全避免这种情况。
- @R说得好,做得好。至少这应该是一个1级编译器警告。
- @R.:如果您在一台不使用ASCII的计算机上开发,那么有许多字符您不能输入,例如使用EBCDIC的IBM大型机,它没有花括号。
- @特博恩:你真的想到这样一个角色吗?
- @R.:是的,大括号。{}
- @tbohne:维基百科声称他们在EBCDIC的c0和d0位置。期望程序员使用\u转义来实现像大括号这样无所不在的东西似乎很荒谬…
- @R:快速的一瞥表明你是对的。但它也包含"可移植性因缺乏编程和网络通信中常用的许多符号而受阻,例如大括号。"以及"它存在于至少六个相互不兼容的版本中"。我想肯定是另一个版本。
- @R.:如果要指定编译的第一个过程是细分为行,并且在这之后引入的任何新行字符将按原样进行处理,那么不必禁止使用ASCII格式的所有内容,这样,string st="Hello\u000D\u000Athere"将生成一个包含回车和新行的12个字符字符串。
- 如果有人持怀疑态度,想要测试Hello World程序,则应该将该类命名为"丑陋的Java"。还有其他有趣的事情可能是由这个…例如,插入LRM字符将允许您编译诸如for (char c? = 1; c? > 0; c?++)之类的代码。
- @Biziclop我们可以称之为当天的评论吗,即使它是8天前发布的?:
由于这还没有解决,这里有一个解释,为什么Unicode转义在任何其他源代码处理之前发生:
其背后的思想是,它允许在不同字符编码之间进行Java源代码的无损翻译。如今,普遍存在对Unicode的支持,这看起来并不是问题,但在过去,西方国家的开发人员很难从他亚洲同事那里接收到包含亚洲字符的源代码,进行一些更改(包括编译和测试),并将结果发回,所有这些都不会对某些内容造成损害。G.
因此,Java源代码可以用任何编码来编写,并允许在标识符、字符和EDCOX1、6个字面和注释中包含大量字符。然后,为了无损地传输它,目标编码不支持的所有字符都将替换为它们的Unicode转义符。
这是一个可逆过程,有趣的一点是,翻译可以由一个工具来完成,它不需要知道Java源代码语法,因为翻译规则不依赖于它。这是因为编译器中的实际Unicode字符的翻译独立于Java源代码语法。它意味着您可以在两个方向上执行任意数量的翻译步骤,而不必更改源代码的含义。
这就是另一个甚至没有提到的奇怪特性的原因:\uuuuuuxxxx语法:
当翻译工具正在转义字符并且遇到已经是转义序列的序列时,它应该在序列中插入一个额外的u,将\ucafe转换为\uucafe。其含义没有改变,但是当转换到另一个方向时,工具应该只删除一个u,并用其unicode字符替换只包含单个u的序列。这样,即使Unicode转义符在来回转换时也保留在其原始形式中。我想,没人用过那个功能…
- 有趣的是,native2ascii似乎没有使用\uu...xxxx语法,
- 是的,native2ascii是为了帮助准备资源包,将它们转换为iso-latin-1,因为Properties.load被固定为只读拉丁语-1。在那里,规则是不同的,没有\uuu…语法,也没有早期处理阶段。在财产档案中,property=multi\u000aline确实与property=multi
line相同。(与使用Java第3.3节中定义的Unicode逃逸)相矛盾?文件的语言规范)
- 请注意,此设计目标可以在没有任何缺点的情况下实现;最简单的方法是禁止\u逃逸以生成U+0000–007F范围内的字符。(所有这些字符都可以由20世纪90年代相关的所有国家编码来代表,也许除了一些控制字符之外,但无论如何都不需要编写Java。)
- ZWOL:嗯,如果你排除了Java代码中不允许的控制字符,你是对的。不过,这意味着要使规则更加复杂。今天讨论这个决定太晚了…
- 啊,以utf8而不是拉丁语或其他方式保存文档的问题。我所有的数据库也因为西方的胡说八道而被破坏了
我将完全无效地添加这一点,仅仅是因为我无法控制自己,而且我还没有看到这一点,这个问题是无效的,因为它包含了一个隐藏的错误前提,即代码在注释中!
在Java源代码中,U000 0D等同于ASCII CR字符。它是一个线条的结束,无论发生在哪里,都是简单明了的。问题中的格式具有误导性,字符序列在语法上实际对应的是:
1 2 3 4 5
| public static void main (String... args) {
// The comment below is no typo.
//
System. out. println("Hello World!");
} |
因此,最正确的答案是:代码执行是因为它不在注释中;它在下一行。"在爪哇中不允许执行注释,正如您所期望的那样。
很多混淆源于这样一个事实:语法高亮器和IDES不够复杂,无法考虑到这种情况。他们要么根本不处理unicode转义,要么在解析代码之后而不是之前处理,就像javac所做的那样。
- 我同意,这不是Java"设计错误",但它是IDE错误。
- 问题在于,对于不熟悉该语言这一特定方面(可能不涉及语法突出显示)的人来说,为什么看起来像注释的代码实际上不是注释。在问题无效的前提下提出反对是不真实的。
- @菲尔:只有在使用特定工具查看时,它才看起来像一条评论,其他人则会显示它。
- @jmore任何人都不应该只有文本编辑器才能读取代码。至少,它违反了最不令人惊讶的原则,即//样式注释一直持续到下一个字符,而不是最终被替换的任何其他序列。评论永远不会被认为是除剥离以外的任何东西。错误的预处理器。
\u000d转义终止注释,因为\u转义在程序标记化之前统一转换为相应的Unicode字符。您也可以使用\u0057\u0057而不是//来开始评论。
这是您的IDE中的一个bug,它的语法应该突出显示该行,以明确说明\u000d结束了注释。
这也是语言中的设计错误。它现在不能被纠正,因为这会破坏依赖它的程序。\u转义应该由编译器仅在"有意义"的上下文(字符串文本和标识符,可能没有其他地方)转换为相应的Unicode字符,或者应该禁止它们在U+0000–007F范围内生成字符,或者两者都转换。这些语义中的任何一个都会阻止注释被\u000d转义终止,而不会干扰\u转义是有用的情况。请注意,这包括使用\u转义在注释内作为一种非拉丁语脚本中对注释进行编码的方法,因为文本编辑器可以采用r查看\u转义的位置比编译器重要。(不过,我不知道任何编辑器或IDE会在任何上下文中将\u转义显示为相应的字符。)
在C族中有一个类似的设计错误,1,其中反斜杠换行是在确定注释边界之前处理的,例如。
1 2
| // this is a comment \
this is still in the comment! |
我提出这一点是为了说明,如果您习惯于思考标记化技术和分析编译器程序员思考标记化技术和分析的方式,那么很容易犯下这个特定的设计错误,并且直到纠正它为时已晚时才意识到这是一个错误。基本上,如果您已经定义了形式语法,然后有人提出了一个语法特殊情况,即三角图、反斜杠换行符、在仅限于ASCII的源文件中编码任意Unicode字符,无论需要嵌入什么,在标记器之前添加转换过程比添加到红色更容易。定义记号赋予器以注意在何处使用该特殊情况是有意义的。
1对于学究:我知道C的这一方面是100%有意的,其基本原理是,我不是在编造这一点,它允许您在穿孔卡片上机械地强制使用任意长行的代码。这仍然是一个错误的设计决定。
- 我不会说这是设计错误。我可以同意你的看法,那是一个糟糕的设计选择,或者是一个有不幸后果的选择,但是我仍然认为它是按照语言设计者的意图工作的:它允许你在文件中的任何地方使用任何Unicode字符,同时保持文件的ASCII编码。
- 我认为,如果理由如前所述,那么反斜杠后面跟着一些特定的其他字符(如!)应该表明物理行的其余部分应该被忽略,下一行的第一个字符应该被视为反斜杠前面的字符的正后。这将允许在第71-72列中穿孔\!,使8列可用于序列号。在某些情况下,标记条技巧可以减少对机器可读数字的需求,但我不认为这会消除它。
- 尽管如此,我认为选择\u的处理阶段比决定在使用前导零作为八进制符号时跟随c的前导要简单得多。虽然八进制符号有时是有用的,但我还没有听到有人提出一个论点,为什么前导零是表示它的好方法。
- @supercat将该特性添加到C89中的人正在概括原始K&R预处理器的行为,而不是从头开始设计特性。我怀疑他们是否熟悉穿孔卡片的最佳实践,我也怀疑该特性是否曾被用于其所述目的,除了一个或两个追溯计算练习。
- "超级猫"如果没有禁止在U+ 0000…U+07F范围内产生字符,我就不会对Java EDCOX1 2的问题进行预标记化转换。正是"这适用于所有地方"和"这是具有句法意义的ASCII字符的别名"的组合,将其从笨拙降级为完全错误。
- @ZWOL:我可以同意这一点,不过一般来说,我不太喜欢语言如何处理非ASCII标识符。由于unicode包含许多同形符号,并且允许unicode标识符的语言通常对其使用施加最小的限制,因此很难生成一个人类可读但语义明确的程序列表。
- @supercat是的,甚至unicode自己对如何在编程语言中做标识符的建议,对我来说都太宽松了。
- @ZWOL:就个人而言,我认为编程语言应该定义紧密和松散的匹配条件,并要求标识符必须紧密匹配才能被视为匹配,但应该隐藏所有松散匹配的标识符(这样的规则应该适用于ASCII中的大小写,但也适用于许多Unicode方案)。因此,如果Foo是在外部上下文中定义的,而Foo是在内部上下文中定义的,那么在内部上下文中,Foo将引用后一个标识符,Foo将是语法错误。将这样的规则应用于同形文字,但在特殊情况下可以用一种方法覆盖它…
- …(例如,明确地告诉编译器"我希望标识符Foo和Foo,或者Χ和X,在这里都可以访问)将有助于防止许多不明确的情况。
- @超级卫星:今天,IDES就这么做。"松散匹配条件"通常由一个字母组成,然后IDE填充剩余的字符,使其成为一个合适的"紧密匹配条件",我认为编译器不应该处理"松散匹配条件"。也就是说,我不会有一个编译器很高兴地将i的出现解析为i,当有人在土耳其地区编译它时,i突然被解析为?。
- @霍尔格:根据我想看到的规则,在定义Six的范围内,即使存在于外部范围内,标识符Six、S?X和S?X等也不可用。冲突可能导致语法错误,这些错误需要显式的"区分这些标识符"指令,但无法更改仍在编译的代码的含义。
- 关于你的"为学究":当然,当时的//单行评论并不存在。因为C有一个不是新行的语句终止符,所以它主要用于长字符串,除了我可以确定K&R中是否存在"字符串文字连接"。
这是一个有意的设计选择,它可以追溯到Java的最初设计。
对于那些询问"谁希望Unicode在注释中转义?"我想他们是母语使用拉丁字符集的人。换句话说,Java的原始设计固有的是,无论Java程序中的合法性如何,用户都可以使用任意的Unicode字符,最常见的是注释和字符串。
可以说,在用于查看源文本的程序(如IDES)中,这样的程序无法解释Unicode转义并显示相应的glyph,这是一个缺点。
- 现在我们的源代码使用UTF-8,并且可以直接使用Unicode字符,不需要转义。
我同意@zwl的说法,这是一个设计错误,但我更批评它。
\u转义在字符串和字符文本中很有用;这是它唯一应该存在的地方。它的处理方式应与其他逃逸的处理方式相同,如
;"\u000A"应完全指"
"。
绝对没有必要让\uxxxx发表评论——没人能读到。
同样,在程序的其他部分也没有使用\uxxxx的意义。唯一的例外可能是在强制包含一些非ASCII字符的公共API中——我们最后一次看到它是什么时候?
设计师们在1995年有他们的理由,但20年后,这似乎是一个错误的选择。
(向读者提问——为什么这个问题一直得到新的选票?这个问题是从某个流行的地方链接的吗?)
- 我猜,您不会在API中使用非ASCII字符的地方闲逛。有人使用它(不是我),例如在亚洲国家。当您在标识符中使用非ASCII字符时,禁止在文档注释中使用它们是没有意义的。然而,允许他们在一个标记内,并允许他们改变标记的含义或边界是不同的事情。
- 他们可以使用正确的文件编码。当你可以做int 整时,为什么要写int \u5431。
- 当您必须根据他们的API编译代码,并且不能使用正确的编码时(假设1995年没有广泛的UTF-8支持),您会怎么做?您只需要调用一个方法,而不想为该单一方法安装操作系统的亚洲语言支持包(请记住,90年代)。
- 这是一个假想的场景吗?我不认为它发生在现实世界中。
- 如果标识符中允许任意字符,情况会更糟,但同时,从某些区域设置访问这些标识符是不可能的。当你设计一种语言时,你应该做出决定。我可以使用一种将符号限制为ASCII的语言,因为我看到了本地化源代码的问题。但我也是一个活跃的全英文StackOverflow网站的用户,所以我(可能还有你)有偏见。我们知道能够(在一个国际网站上)与其他人讨论代码的价值。顺便说一下,我留下了一个解释原意的答案。
- 现在比1995年更清楚的是,如果你想编程的话,你最好懂英语。编程是一种国际交互,几乎所有资源都是英语。
- @霍尔格:标识符中的非ASCII是另一种蠕虫病毒,因为它不仅是非ASCII字母数字,而且包含了太多的内容,包括控制代码:stackoverflow.com/questions/4838507/…
- 我认为这并没有改变。Java的文档大部分时间都是英语。有一个日文翻译维持了一段时间,但是保持两种语言并不能真正支持在世界各地维护它的想法(它相反)。在此之前,没有任何主流语言在标识符中支持Unicode。所以我猜,有人认为本地化的源代码是下一件大事。谢天谢地,它没有起飞。
- @Ninjalj:是的,我喜欢你可以用从右到左的嵌入式文字来做什么,但同样简单的是,a?和ä是不同的标识符(因为一个是U+0061U+0308,另一个是U+00E4)。
- @霍尔格:RTL本身也会令人困惑。有一个问题,我现在找不到操作试图匹配字符串上的子字符串的地方:参数被颠倒了。
- @Stephenp-你可能认为%n在format()中。
正好表示0x0a字符,见docs.oracle.com/javase/specs/jls/se8/html/jls-3.html jls-3.1‌&8203;0.6
- @我觉得unicode在评论中是有效的…更具体地说是一个记录评论/**……*/对于将生成到HTML JavaDoc页中的描述,现在在这种情况下,我可能仍然使用一个文本换行符来处理这个问题,对于文档注释,除非我在注释中有*和/的Unicode字符,因为文档注释不会被单个换行符。
- @匿名-很好。但是我们可以使用XML转义-⪹->?
- @当我要做一个没有英文名字的模型时,我该怎么做?如果你处理过法律、商业或类似领域缺少这些东西,这是很常见的。特别是在法律领域,词语具有非常特殊的含义。想象一下,如果标准字母表没有c、x或q,那么现在你有了一个叫做"kommonlaw"的类或者其他的类。你想用"c"。在你的世界里,那是错误的。但如果科蒙洛的意思是其他的呢?现在怎么办?在某种程度上,你可能会尝试使用一种允许你使用"c"的语言。
- @haakonl&248;tveit-不能直接使用字符,而不是转义序列,例如class Løtveit而不是class L\u00D8tveit
- 这对我来说很好,但是你必须在某个地方写下"new l&248;e()",你可能会很快就厌倦了复制&248;。让你去那些地方可能会更容易保持你的理智。(或者您只需要使用IBM国际布局,但这是因为它支持大多数西欧字符。但是还有拼音等。)
- @haakonl&248;tveit——我没有输入或复制@HaakonLøtveit,编辑为我自动完成。对于Java也是一样的。即使我必须复制ø,它也可能比查找和键入其unicode更容易。
- 对。你今天的编辑,在2016年就这么做了。但是Java是在1995发布的。当时Emacs没有语义自动完成,是Java最先进的东西。它甚至没有Unicode支持。
唯一能够回答为什么实现Unicode转义的人是编写规范的人。
一个合理的原因是,希望让整个BMP成为Java源代码的可能特征。但这会带来一个问题:
- 您希望能够使用任何BMP字符。
- 您希望能够输入任何BMP字符相当容易。一种方法是使用Unicode转义。
- 您希望使词汇规范易于人类阅读和编写,并合理地易于实现。
当unicode逃逸进入混乱状态时,这是非常困难的:它创建了一整套新的lexer规则。
最简单的方法是分两步进行词法分析:首先搜索并用它所代表的字符替换所有Unicode转义,然后像Unicode转义不存在一样解析结果文档。
这样做的好处是它易于指定,因此它使规范更简单,并且易于实现。
缺点是,你的例子。
- 或者,将uxxx的使用限制为标识符、字符串文本和字符常量。这就是C11的作用。
- 不过,这确实使解析器规则复杂化了,因为这些规则定义了这些东西,我猜测这也是它之所以如此的部分原因。
编译器不仅将Unicode转义符转换为它们在将程序解析为标记之前表示的字符,而且在丢弃注释和空白之前也会这样做。
此程序包含一个Unicode转义符(u000d),位于其唯一注释中。正如注释所告诉您的,这个转义表示换行符,编译器在放弃注释之前会对其进行适当的翻译。
这取决于平台。在某些平台上,如Unix,它会工作;在其他平台上,如Windows,它不会工作。虽然肉眼看输出可能相同,但如果将其保存在文件中或通过管道传输到其他程序进行后续处理,则很容易导致问题。
- 尽管你的"答案"可能很有说服力,但实际上它根本不是一个答案。OP的问题是"为什么允许这样做",但这是一个解释,说明了它是如何工作的……这是OP已经提供的。
- 您是否有任何来源来确认这是依赖于平台的?如果这是真的,我会认为Java完全被破坏了(不管怎么说,这只是棺材里的另一个钉子)。
- Java编译器将一个裸EDCX1 OR 0称为终止单行EDCOX1×1注释,甚至在Windows上。(用Oracle Java 1.7和IBM Java 1.8在Windows 7上进行测试,只要确定……)