Java标识符中的“连接字符”是什么?


208

我正在阅读SCJP,对此行有疑问:

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

它指出有效的标识符名称可以下划线之的连接字符开头。我以为下划线是唯一有效的选择?还有哪些其他连接字符


2
关于“货币字符”:对此问题的英国访问者可能会感到惊讶,并且想知道,与能够以“ a”货币字符开头的一致,Java标识符在法律上可以以英镑符号(£)开头。
8bitjunkie 2014年

11
请注意,由于Java 8 _是“不赞成使用的”标识符。具体来说,编译器发出以下警告:(在Java SE 8之后的发行版中可能不支持使用'_'作为标识符)
aioobe 2014年

4
@aioobe是的。布莱恩·格茨(Brian Goetz)表示,他们正在“回收” _用于将来的语言功能。该标识符开始以下划线仍然是好的,但如果用作拉姆达参数名称的单下划线是错误的,并警告其他地方。
Boann 2014年

1
对于字节码,任何不包含序列的东西. ; [ / < > :都会去:stackoverflow.com/questions/26791204 / ... docs.oracle.com/javase/specs/jvms/se7/html / ...其他所有内容都是 Java的限制。
西罗Santilli郝海东冠状病六四事件法轮功2015年

@Boann有趣的是,他们不允许在lambda中使用它,但它可能会以“忽略此参数”标识符的形式返回,例如,将在lambda中使用。我只是想这样使用它:_, _ -> doSomething();
user31389

Answers:


268

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

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 + " ");
}

版画

$ _¢£¤؋৻₱₱₱₱₱₱₱₹₹_ _ _ ¢ ¥ ¥


109
我期待有一天继承一些使用这些标识符的代码!
Marko Topolnik

58
@MarkoTopolnik请注意您的要求。;)
彼得·劳瑞

3
顺便说一句,您也可以使用任何一种货币符号。int ৲, ¤, ₪₪₪₪;:D
彼得·劳里

17
我可能会把其中一两个扔到我的代码中,只是为了踢!并测试构建系统是否确实符合UTF-8。
Marko Topolnik

82
@GrahamBorland如何if( ⁀ ‿ ⁀ == ⁀ ⁔ ⁀)if ($ == $)if (¢ + ¢== ₡)if (B + ︳!= ฿)
彼得Lawrey

25

遍历整个65k字符并询问Character.isJavaIdentifierStart(c)。答案是:“ undertie”十进制8255


14
我无法抗拒(在Scala中):(1 to 65535).map(_.toChar).filter(Character.isJavaIdentifierStart).size-产生48529个字符...
Tomasz Nurkiewicz 2012年

似乎有近65K和12K和8.5K等几个大字
马库斯Mikkolainen

如果您说“!isLetter”和“!isDigit”,则不会产生收益
Markus Mikkolainen 2012年

2546 + 2547至少是“箱形图...”
Markus Mikkolainen 2012年

3
总数= 90648,但我要输入Character.MAX_CODE_POINT,可能超过2<<16
马丁·考特

7

合法的Java标识符的权威性规范可以在Java Language Specification中找到


3
我不确定实际上是否完全回答了(隐含的)哪个字符可以启动Java标识符的问题。通过以下链接,我们最终到达Character.isJavaIdentifierStart(),它声明只有当以下条件之一为真时,字符才能启动Java标识符:... ch是货币符号(例如 “ $”);ch是连接标点字符(例如 “ _”)。
CVn 2012年

1
规范似乎将最终可接受的字符列表留给实现,因此对于每个人来说,它可能有所不同。
格雷格(Greg Hewgill)

3
@GregHewgill考虑到其他所有内容的详细程度,这真是愚蠢。我认为这些是实际的Unicode字符类,它们是在Unicode标准中定义的(在其他位置?)。isJavaIdentifierStart()提到了getType(),货币符号和连接器标点符号也是该函数可以返回的类型,因此可以在此处给出列表。实际上,“常规类别”是Unicode标准中的特定术语。因此,有效的值是L[全部], ,Nl,。Sc Pc
Random832

3
@GregHewgill是正确的。该规范简短明了,由Character.isJavaIdentifierStart()和Character.isJavaIdentifierPart()定义。结束。要记住的关键是Unicode在不断发展。不要陷入将字符集视为完成的陷阱(拉丁是一个可怕的例子;请忽略它)。角色始终被创建。问问你的日本朋友。期望合法的Java标识符会随着时间而改变-这是有意的。关键是让人们用人类语言编写代码。这导致了允许更改的严格要求。
詹姆斯·摩尔

6

这是 Unicode中的连接器字符列表。您不会在键盘上找到它们。

U + 005F下线_
U + 203F UNDERTIE‿U
+ 2040字符领带⁀U
+ 2054逆向⁔U
+ FE33垂直低线的表示形式︳
U + FE34垂直波浪低线的表示
形式︴U + FE4D虚线﹍
U + FE4E中心线低线﹎
U + FE4F WAVY低线﹏
U + FF3F FULLWIDTH低线_


5
我不知道您使用的是哪种键盘布局,但是我可以很容易地输入_(U + 005F):)
bdonlan

4

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

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

请注意,在Java中,字符信息基于Unicode标准,该标准通过为连接字符分配通用类别Pc来标识连接字符,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;

显然,对于以下两个连接字符(向后兼容... oops!),上述声明无法在jdk1.7.0_80和jdk1.8.0_51上编译,

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

无论如何,除了细节之外,该考试仅侧重于基本拉丁字符集

另外,对于Java中的合法标识符,此处提供了规范。使用Character类API获取更多详细信息。


1

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

我曾经在属性值中的一段XML中拥有此属性,该值持有对该XML的另一段的引用。由于ZWNJ是“零宽度”,因此无法看到(除非与光标一起行走,否则它会显示在前面的字符上)。在日志文件和/或控制台输出中也看不到它。但是它一直都存在:将其复制并粘贴到搜索字段中就可以了,因此找不到参考位置。在搜索字段中键入(字符串的可见部分)字符串,但是找到了参考位置。花了我一段时间来解决这个问题。

使用欧洲键盘布局时,键入零宽度非连接器实际上非常容易(太简单),至少在其德语变体中,例如“ Europatastatur 2.02”-可通过AltGr +“。”到达,两个键不幸的是,在大多数键盘上,它们是直接相邻放置的,很容易被意外地撞在一起。

回到Java:我想很好,您可以编写如下代码:

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

第二个我附加了零宽度非连接符(在上面的代码中,stackoverflow的编辑器中没法做到这一点),但这没有用。IntelliJ(16.3.3)没有抱怨,但是JavaC(Java 8)确实抱怨了一个已经定义的标识符-似乎JavaC实际上允许ZWNJ字符作为标识符的一部分,但是当使用反射来查看它做什么时,ZWNJ字符从标识符中删除-像‿这样的字符不是。


0

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

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!

它包括大多数控制字符!我的意思是铃铛和狗屎!您可以让您的源代码敲钟!或使用仅在某些时候显示的字符,例如软连字符。


它包含DEL字符\ u007f。:-(
托德·奥布莱恩
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.