“ การเชื่อมต่ออักขระ” ในตัวระบุ Java คืออะไร


208

ฉันกำลังอ่านสำหรับ SCJP และฉันมีคำถามเกี่ยวกับสายนี้:

ตัวระบุต้องเริ่มต้นด้วยตัวอักษรตัวอักษรสกุลเงิน ($) หรือตัวเชื่อมต่อเช่นขีดล่าง (_) ตัวระบุไม่สามารถเริ่มต้นด้วยตัวเลขได้!

มันระบุว่าชื่อตัวระบุที่ถูกต้องสามารถเริ่มต้นด้วยตัวเชื่อมต่อเช่นขีดล่าง ฉันคิดว่าขีดเส้นใต้เป็นตัวเลือกที่ถูกต้องเท่านั้น? มีอักขระเชื่อมต่ออื่นใดอีกบ้าง


2
เกี่ยวกับ "ตัวอักษรสกุลเงิน": ผู้เข้าชมในสหราชอาณาจักรสำหรับคำถามนี้อาจแปลกใจและสนใจที่จะรู้ว่าสอดคล้องกับความสามารถในการเริ่มต้นด้วยตัวอักษรสกุลเงิน "a" ตัวระบุ Java สามารถตามกฎหมายเริ่มต้นด้วยสัญลักษณ์ปอนด์ (£)
8bitjunkie

11
โปรดทราบว่าตั้งแต่ Java 8 _เป็นตัวระบุ "ที่เลิกใช้แล้ว" โดยเฉพาะคอมไพเลอร์จะส่งเสียงเตือนดังต่อไปนี้(ใช้ '_' เป็นตัวระบุอาจจะไม่ได้รับการสนับสนุนในรุ่นหลัง Java SE 8)
aioobe

4
@aioobe Yup ไบรอันเก๊กล่าวว่าพวกเขาจะ "หนุ่มแน่น"_สำหรับการใช้งานในลักษณะภาษาในอนาคต ตัวระบุที่ขึ้นต้นด้วยขีดล่างยังคงใช้ได้ แต่ขีดล่างเดียวคือข้อผิดพลาดหากใช้เป็นชื่อพารามิเตอร์แลมบ์ดาและคำเตือนทุกที่อื่น
Boann

1
สำหรับ bytecode ทุกอย่างที่เรียงลำดับตามที่ไม่มีใน. ; [ / < > :: stackoverflow.com/questions/26791204/ .. docs.oracle.com/javase/specs/jvms/se7/html/…ทุกอย่างเป็นข้อ จำกัด ของ Java เท่านั้น
Ciro Santilli 法轮功冠状病六四事件法轮功

@Boann สิ่งที่ตลกคือพวกเขาไม่อนุญาตให้ใช้งานใน lambdas แต่มันอาจจะกลับมาเป็นตัวระบุ "ละเว้นอาร์กิวเมนต์นี้" ซึ่งจะถูกใช้เช่นใน lambdas ฉันแค่พยายามใช้มันอย่างนี้: _, _ -> doSomething();.
user31389

คำตอบ:


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 ระวังสิ่งที่คุณต้องการ ;)
Peter Lawrey

3
BTW คุณสามารถใช้สัญลักษณ์สกุลเงินใดก็ได้เช่นกัน int ৲, ¤, ₪₪₪₪;: D
Peter Lawrey

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

ดูเหมือนว่าจะมีตัวละครไม่กี่ตัวที่อยู่ใกล้ 65k และ 12k และ 8.5k เป็นต้น
Markus Mikkolainen

ไม่ยอมถ้าคุณพูดว่า "! isLetter" และ "! isDigit"
Markus Mikkolainen

2546 + 2547 atleast "การวาดกล่อง ... "
Markus Mikkolainen

3
นับรวม = 90,648 แต่ผมกำลังจะไปซึ่งอาจมากกว่าคือCharacter.MAX_CODE_POINT 2<<16
Martijn Courteaux

7

ข้อกำหนดที่ชัดเจนของตัวระบุ Java ตามกฎหมายสามารถพบได้ในJava Language ข้อกำหนด


3
ฉันไม่แน่ใจว่าจริงๆตอบคำถาม (โดยนัย) อย่างเต็มที่ซึ่งตัวละครอาจเริ่มตัวระบุ Java ลิงก์ต่อไปนี้เราจะสิ้นสุดที่Character.isJavaIdentifierStart ()ซึ่งระบุตัวละครอาจเริ่มตัวระบุ Java หากและหากเงื่อนไขใด ๆ ต่อไปนี้เป็นจริง: ... ch เป็นสัญลักษณ์สกุลเงิน ( เช่น "$"); ch คืออักขระเครื่องหมายวรรคตอนที่เชื่อมต่อ ( เช่น "_")
CVn

1
ดูเหมือนว่าข้อมูลจำเพาะออกจากรายการสุดท้ายของอักขระที่ยอมรับได้จนถึงการนำไปใช้ดังนั้นจึงอาจมีความแตกต่างสำหรับทุกคน
เกร็กฮิวกิลล์

3
@ GregHewgill นั่นคงเป็นเรื่องที่โง่เง่าโดยพิจารณาว่าทุกสิ่งทุกอย่างระบุไว้อย่างแน่นหนาอย่างไร ฉันคิดว่านี่เป็นคลาสอักขระ Unicode จริงซึ่งกำหนดไว้ (ที่ไหนอีก?) ในมาตรฐาน Unicode isJavaIdentifierStart () กล่าวถึง getType () และสัญลักษณ์สกุลเงินและเครื่องหมายวรรคตอนของตัวเชื่อมต่อเป็นทั้งชนิดที่สามารถส่งคืนโดยฟังก์ชันนั้นดังนั้นรายการอาจถูกกำหนดไว้ที่นั่น "หมวดหมู่ทั่วไป" เป็นคำเฉพาะในมาตรฐาน Unicode ดังนั้นค่าที่ถูกต้องจะเป็น[ทั้งหมด]L , , NlScPc
Random832

3
@GregHewgill ถูกต้อง ข้อมูลจำเพาะสั้นและชัดเจนและมันถูกกำหนดโดย Character.isJavaIdentifierStart () และ Character.isJavaIdentifierPart () ตอนจบ. สิ่งสำคัญที่ต้องจำคือ Unicode นั้นกำลังวิวัฒนาการ อย่าตกหลุมพรางของการคิดชุดอักขระเมื่อเสร็จแล้ว (ละตินเป็นตัวอย่างที่แย่มาก; ตัวละครถูกสร้างขึ้นตลอดเวลา ถามเพื่อนชาวญี่ปุ่นของคุณ คาดว่าตัวระบุจาวาที่ถูกต้องตามกฎหมายจะเปลี่ยนไปตามกาลเวลา - และนั่นคือเจตนา ประเด็นคือเพื่อให้ผู้คนเขียนโค้ดเป็นภาษามนุษย์ สิ่งนี้นำไปสู่ความต้องการที่ยากสำหรับการเปลี่ยนแปลง
James Moore

6

นี่คือรายการของตัวเชื่อมต่ออักขระใน Unicode คุณจะไม่พบพวกเขาบนคีย์บอร์ดของคุณ

U + 005F LOW สาย _
U + 203F UNDERTIE ‿
U + 2040 CHARACTER TIE ⁀
U + 2054 INVERTED UNDERTIE ⁔
U + FE33 ฟอร์มการนำเสนอสำหรับแนวตั้ง LOW สาย _ U
+ FE34 ฟอร์มการนำเสนอสำหรับแนวตั้งลอน LOW สาย︴
U + FE4D ประ LOW สาย ﹍
U + FE4E CENTRELINE LOW LINE ﹎
U + FE4F WAV สายไฟต่ำ﹏
U + FF3F FULLWIDTH สายต่ำเต็มรูปแบบ _


5
ผมไม่ทราบว่าสิ่งที่แป้นพิมพ์รูปแบบที่คุณใช้ แต่แน่นอนฉันสามารถพิมพ์ _ (U + 005F) ได้อย่างง่ายดายพอ :)
bdonlan

4

อักขระการเชื่อมต่อใช้เพื่อเชื่อมต่ออักขระสองตัว

ใน Java เป็นตัวละครที่เชื่อมต่อกันเป็นหนึ่งซึ่งCharacter.getType (int codepoint) / Character.getType (ถ่าน CH)ส่งกลับค่าเท่ากับCharacter.CONNECTOR_PUNCTUATION

โปรดทราบว่าใน Java ข้อมูลตัวอักษรที่อยู่บนพื้นฐานของมาตรฐาน Unicode ซึ่งระบุการเชื่อมต่อตัวละครโดยการกำหนดหมวดหมู่ทั่วไปชิ้นซึ่งเป็นนามแฝงสำหรับ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 สำหรับอักขระการเชื่อมต่อสองตัวต่อไปนี้ (ความเข้ากันได้แบบย้อนหลัง ... โอ๊ะโอ !!!

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

อย่างไรก็ตามรายละเอียดนอกเหนือจากนั้นการสอบจะเน้นเฉพาะชุดอักขระภาษาละตินขั้นพื้นฐานเท่านั้น

นอกจากนี้สำหรับ identifers กฎหมายในชวาสเปคที่มีให้ที่นี่ ใช้ API คลาสตัวละครเพื่อรับรายละเอียดเพิ่มเติม


1

หนึ่งในตัวละครที่สนุกและดีที่สุดที่ได้รับอนุญาตในตัวระบุ Java (แต่ไม่ใช่ตอนเริ่มต้น) คือตัวอักษร unicode ชื่อ "Zero Width Non Joiner" (& zwnj ;, U + 200C, https://en.wikipedia.org / wiki / Zero-width_non-joiner )

ฉันมีสิ่งนี้ครั้งเดียวในส่วนของ XML ภายในค่าคุณลักษณะที่มีการอ้างอิงถึงส่วนอื่นของ XML นั้น เนื่องจาก ZWNJ เป็น "ความกว้างเป็นศูนย์" จึงไม่สามารถมองเห็นได้ (ยกเว้นเมื่อเดินไปพร้อมกับเคอร์เซอร์จึงปรากฏบนอักขระก่อนหน้านี้) ไม่สามารถมองเห็นได้ใน logfile และ / หรือคอนโซลเอาต์พุต แต่มันอยู่ที่นั่นตลอดเวลา: คัดลอกและวางลงในช่องค้นหาและได้รับมันจึงไม่พบตำแหน่งที่อ้างอิง การพิมพ์สตริง (ส่วนที่มองเห็นได้ของ) ลงในช่องค้นหาอย่างไรก็ตามพบตำแหน่งที่อ้างอิง เอาฉันไปคิดดู

การพิมพ์ Zero-Width-Non-Joiner นั้นง่ายมาก (ง่ายเกินไป) เมื่อใช้รูปแบบแป้นพิมพ์ของยุโรปอย่างน้อยในรูปแบบภาษาเยอรมันเช่น "Europatastatur 2.02" - สามารถเข้าถึงได้ด้วย AltGr + "สองปุ่มซึ่ง โชคไม่ดีที่ตั้งอยู่ติดกันบนคีย์บอร์ดส่วนใหญ่และสามารถชนเข้าด้วยกันได้อย่างง่ายดายโดยไม่ตั้งใจ

กลับไปที่ Java: ฉันคิดว่าดีคุณสามารถเขียนโค้ดดังนี้:

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

ด้วยตัวที่สองที่ฉันเพิ่มโดย zero-width-non-joiner (ไม่สามารถทำได้ในโค้ดด้านบนที่ถูกสแนปในเอดิเตอร์ของ 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!

มันรวมถึงตัวควบคุมส่วนใหญ่! ฉันหมายถึงระฆังและอึ! คุณสามารถทำให้ซอร์สโค้ดของคุณดังขึ้นเป็นเสียงระฆัง fn! หรือใช้ตัวละครซึ่งจะปรากฏเฉพาะบางครั้งเช่นยัติภังค์อ่อน


มันมี \ u007f, อักขระ DEL :-(
Todd O'Bryan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.