Java中的合法标识符

我正在阅读SCJP,我对这一行有个疑问:

标识符必须以字母,货币字符($)或连接字符(如下划线(_))开头。 标识符不能以数字开头!

它指出一个有效的标识符名称可以以连接字符(如下划线)开头。 我以为下划线是唯一有效的select? 还有什么其他的连接字符

这是连接字符的列表。 这些是用来连接单词的字符。

http://www.fileformat.info/info/unicode/category/Pc/list.htm

 U+005F _ LOW LINE U+203F ‿ UNDERTIE U+2040 ⁀ CHARACTER TIE U+2054 ⁔ INVERTED UNDERTIE U+FE33 ︳ PRESENTATION FORM FOR VERTICAL LOW LINE U+FE34 ︴ PRESENTATION FORM FOR VERTICAL WAVY LOW LINE U+FE4D ﹍ DASHED LOW LINE U+FE4E ﹎ CENTRELINE LOW LINE U+FE4F ﹏ WAVY LOW LINE U+FF3F _ FULLWIDTH LOW LINE 

这编译在Java 7上。

 int _, ‿, ⁀, ⁔, ︳, ︴, ﹍, ﹎, ﹏, _; 

一个例子。 在这种情况下, tp是列的名称和给定行的值。

 Column<Double> ︴tp︴ = table.getColumn("tp", double.class); double tp = row.getDouble(︴tp︴); 

下列

 for (int i = Character.MIN_CODE_POINT; i <= Character.MAX_CODE_POINT; i++) if (Character.isJavaIdentifierStart(i) && !Character.isAlphabetic(i)) System.out.print((char) i + " "); } 

版画

$ _¢£﹏৲৳৳৻௹௹₢₣₤₥₦₧₨₫₫₫₫₰₱﹏₳₴₵₶₷₸︴︴︴﹍﹍﹎﹏ $ $ _¢£₩

迭代整个65k字符并询问Character.isJavaIdentifierStart(c) 。 答案是:“undertie”小数8255

在Java语言规范中可以find合法的Java标识符的权威规范 。

以下是 Unicode中连接器字符的列表 。 你不会在你的键盘上find它们。

U + 005F LOW LINE _
U + 203F UNDERTIE‿
U + 2040 CHARACTER TIE⁀
U + 2054颠倒的底层⁔
U + FE33展示forms垂直低线_
U + FE34演示模式垂直波低线︴
U + FE4D DASHED LOW LINE﹍
U + FE4E CENTRELINE LOW LINE﹎
U + FE4F WAVY LOW LINE﹏
U + FF3F FULLWIDTH LOW LINE _

连接字符用于连接两个字符。

在Java中,连接字符是Character.getType(int codePoint) / Character.getType(char ch)返回一个等于Character.CONNECTOR_PUNCTUATION的值的字符 。

请注意,在Java中,字符信息基于Unicode标准,通过为它们分配一般类别Pc(它是Connector_Punctuation的别名)来标识连接字符。

下面的代码片断,

 for (int i = Character.MIN_CODE_POINT; i <= Character.MAX_CODE_POINT; i++) { if (Character.getType(i) == Character.CONNECTOR_PUNCTUATION && Character.isJavaIdentifierStart(i)) { System.out.println("character: " + String.valueOf(Character.toChars(i)) + ", codepoint: " + i + ", hexcode: " + Integer.toHexString(i)); } } 

打印可用于在jdk1.6.0_45上启动标识符的连接字符

 character: _, codepoint: 95, hexcode: 5f character: ‿, codepoint: 8255, hexcode: 203f character: ⁀, codepoint: 8256, hexcode: 2040 character: ⁔, codepoint: 8276, hexcode: 2054 character: ・, codepoint: 12539, hexcode: 30fb character: ︳, codepoint: 65075, hexcode: fe33 character: ︴, codepoint: 65076, hexcode: fe34 character: ﹍, codepoint: 65101, hexcode: fe4d character: ﹎, codepoint: 65102, hexcode: fe4e character: ﹏, codepoint: 65103, hexcode: fe4f character: _, codepoint: 65343, hexcode: ff3f character: ・, codepoint: 65381, hexcode: ff65 

下面编译jdk1.6.0_45,

 int _, ‿, ⁀, ⁔, ・, ︳, ︴, ﹍, ﹎, ﹏, _, ・ = 0; 

显然,上面的声明无法在jdk1.7.0_80&jdk1.8.0_51上为以下两个连接字符(向后兼容… oops !!!)编译,

 character: ・, codepoint: 12539, hexcode: 30fb character: ・, codepoint: 65381, hexcode: ff65 

无论如何,除了细节外, 考试只关注基本拉丁字符集

而且,对于Java中的合法标识, 这里提供了这个规范。 使用Character类API获取更多细节。

您可以标识符中使用的字符列表(而不仅仅是在开始时)更加有趣:

 for (int i = Character.MIN_CODE_POINT; i <= Character.MAX_CODE_POINT; i++) if (Character.isJavaIdentifierPart(i) && !Character.isAlphabetic(i)) System.out.print((char) i + " "); 

清单是:

 I wanted to post the output, but it's forbidden by the SO spam filter. That's how fun it is! 

它包含了大部分的控制字符! 我的意思是钟声和狗屎! 你可以让你的源代码响铃! 或者使用有时只显示的字符,如软连字符。

Java标识符允许使用的最有趣的字符之一(但不是在开始时)是名为“零宽度非Joiner”的Unicode字符(&zwnj; U + 200C, https ://en.wikipedia.org / wiki / Zero-width_non-joiner )。

我曾经有一次在一个XML中的一个属性值中持有对另一个XML的引用。 由于ZWNJ是“零宽度”,所以不能被看到(除了与光标一起行走之外,它在之前的字符上显示)。 在日志文件和/或控制台输出中也看不到它。 但它一直在那里:复制并粘贴到search字段得到它,因此没有find引用的位置。 键入string(的可见部分)到search字段中,但find了引用的位置。 花了我一段时间来弄清楚这一点。

使用欧式键盘布局时,键入零宽度非连接器实际上非常简单(太简单了),至less在德语版本中是这样的,例如“Europatastatur 2.02” – 可以用AltGr +“。”获得,两个键不幸的是,它们在大多数键盘上直接相邻,很容易被偶然碰撞到一起。

回到Java:我觉得很好,你可以写这样的代码:

 void foo() { int i = 1; int i‌ = 2; } 

与第二个我附加一个零宽度非joiner(不能这样做,在上面的代码剪切在stackoverflow的编辑器),但没有奏效。 IntelliJ(16.3.3)并没有抱怨,但JavaC(Java 8)确实抱怨已经定义好的标识符 – 看起来JavaC实际上允许ZWNJ字符作为标识符的一部分,但是当使用reflection来看它是什么时,ZWNJ字符被剥离标识符 – 像‿这样的字符不是。