Các ký tự kết nối là gì trong các định danh Java là gì?


208

Tôi đang đọc cho SCJP và tôi có một câu hỏi liên quan đến dòng này:

Mã định danh phải bắt đầu bằng một chữ cái, ký tự tiền tệ ($) hoặc ký tự kết nối, chẳng hạn như dấu gạch dưới (_). Định danh không thể bắt đầu bằng một con số!

Nó tuyên bố rằng một tên định danh hợp lệ có thể bắt đầu bằng một ký tự kết nối, chẳng hạn như gạch dưới. Tôi nghĩ rằng dấu gạch dưới là lựa chọn hợp lệ duy nhất? Những nhân vật kết nối khác là gì?


2
Về "một ký tự tiền tệ": Khách truy cập Vương quốc Anh cho câu hỏi này có thể ngạc nhiên và thích thú khi biết rằng, phù hợp với việc có thể bắt đầu bằng "ký tự" tiền tệ, các định danh Java có thể, bắt đầu bằng ký hiệu bảng Anh (£).
8bitjunkie

11
Lưu ý rằng kể từ Java 8, _là một định danh "không dùng nữa". Cụ thể, trình biên dịch phát ra cảnh báo sau: (sử dụng '_' làm định danh có thể không được hỗ trợ trong các bản phát hành sau Java SE 8) .
aioobe

4
@aioobe Yup. Brian Goetz nói rằng họ đang "đòi lại" _để sử dụng trong các tính năng ngôn ngữ trong tương lai . Các định danh bắt đầu bằng dấu gạch dưới vẫn ổn, nhưng một dấu gạch dưới đơn là lỗi nếu được sử dụng làm tên tham số lambda và cảnh báo ở mọi nơi khác.
Boann

1
Đối với mã byte, mọi thứ theo chuỗi không chứa . ; [ / < > :đi: stackoverflow.com/questions/26791204/ Thẻ docs.oracle.com/javase/specs/jvms/se7/html/ trộm Mọi thứ khác chỉ là hạn chế của Java.
Ciro Santilli 郝海东 冠状 病 事件

@Boann Điều buồn cười là họ không cho phép sử dụng nó trong lambdas, nhưng nó có thể sẽ quay trở lại như một định danh "bỏ qua đối số này", sẽ được sử dụng, ví dụ như trong lambdas. Tôi chỉ cố gắng sử dụng nó như thế này : _, _ -> doSomething();.
dùng31389

Câu trả lời:


268

Dưới đây là danh sách các nhân vật kết nối. Đây là những ký tự được sử dụng để kết nối các từ.

http://www.fileformat.info/info/unicode/carget/Pc/list.htmlm

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

Điều này biên dịch trên Java 7.

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

Một ví dụ. Trong trường hợp tpnày là tên của một cột và giá trị cho một hàng nhất định.

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

double tp = row.getDouble(︴tp︴);

Sau đây

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

in

$ _ ¢ £ ¤ ¥ € € € € € € $ _ ¢


109
Tôi đang mong chờ đến ngày tôi thừa hưởng một số mã sử dụng các mã định danh này!
Marko Topolnik

58
@MarkoTopolnik Hãy cẩn thận những gì bạn muốn. ;)
Peter Lawrey

3
BTW Bạn cũng có thể sử dụng bất kỳ ký hiệu tiền tệ nào. int ৲, ¤, ₪₪₪₪;: D
Peter Lawrey

17
Tôi có thể ném một hoặc hai trong số này vào mã của mình, chỉ để đá! Và để kiểm tra xem hệ thống xây dựng có thực sự tuân thủ UTF-8 hay không.
Marko Topolnik

82
@GrahamBorland Làm thế nào về if( ⁀ ‿ ⁀ == ⁀ ⁔ ⁀) hoặc if ($ == $)hoặc if (¢ + ¢== ₡)hoặcif (B + ︳!= ฿)
Peter Lawrey

25

Lặp lại qua toàn bộ ký tự 65k và hỏi Character.isJavaIdentifierStart(c). Câu trả lời là: "undertie" thập phân 8255


14
Tôi không thể cưỡng lại (trong Scala): (1 to 65535).map(_.toChar).filter(Character.isJavaIdentifierStart).size- mang lại 48529 ký tự ...
Tomasz Nurkiewicz

dường như có một vài nhân vật gần 65k và 12k và 8,5k, v.v.
Markus Mikkolainen

không mang lại kết quả nếu bạn nói "! isLetter" và "! isDigit"
Markus Mikkolainen

2546 + 2547 ít nhất là "vẽ hộp ..."
Markus Mikkolainen

3
Tổng số = 90648, nhưng tôi sẽ Character.MAX_CODE_POINT, có lẽ nhiều hơn thế 2<<16.
Martijn Courteaux

7

Đặc tả kỹ thuật dứt khoát của một định danh Java hợp pháp có thể được tìm thấy trong Đặc tả ngôn ngữ Java .


3
Tôi không chắc chắn rằng thực sự trả lời đầy đủ câu hỏi (ngụ ý) về các ký tự nào có thể bắt đầu một định danh Java. Theo các liên kết, chúng tôi kết thúc tại Character.isJavaIdentifierStart () trong đó nêu rõ Một ký tự có thể bắt đầu một định danh Java khi và chỉ khi một trong các điều kiện sau là đúng: ... ch là ký hiệu tiền tệ ( chẳng hạn như "$"); ch là một ký tự dấu chấm câu kết nối ( chẳng hạn như "_").
một CVn

1
Dường như đặc tả kỹ thuật để lại danh sách cuối cùng của các ký tự được chấp nhận cho đến khi triển khai, do đó nó có thể có khả năng khác nhau đối với mọi người.
Greg Hewgill

3
@GregHewgill Điều đó thật ngu ngốc, xem xét mọi thứ khác được chỉ định chặt chẽ như thế nào. Tôi nghĩ rằng đây là các lớp ký tự Unicode thực tế, được định nghĩa (ở đâu khác?) Trong tiêu chuẩn Unicode. isJavaIdentifierStart () đề cập đến getType () và ký hiệu tiền tệ và dấu chấm câu kết nối là cả hai loại có thể được trả về bởi hàm đó, vì vậy danh sách có thể được cung cấp ở đó. "Danh mục chung" trên thực tế là một thuật ngữ cụ thể trong tiêu chuẩn Unicode. Vì vậy, các giá trị hợp lệ sẽ là L[tất cả], Nl, Sc, Pc.
Ngẫu nhiên832

3
@GregHewgill là chính xác. Thông số kỹ thuật này ngắn và rõ ràng và được xác định bởi Character.isJavaIdentifierStart () và Character.isJavaIdentifierPart (). Kết thúc. Điều quan trọng cần nhớ là Unicode đang phát triển; đừng rơi vào cái bẫy nghĩ về các bộ ký tự như đã hoàn thành (tiếng Latin là một ví dụ tồi tệ; bỏ qua nó). Nhân vật được tạo ra tất cả các thời gian. Hỏi bạn bè Nhật Bản của bạn. Mong đợi các định danh java hợp pháp sẽ thay đổi theo thời gian - và đó là cố ý. Vấn đề là để mọi người viết mã bằng ngôn ngữ của con người. Điều đó dẫn đến một yêu cầu khó khăn cho phép thay đổi.
James Moore

6

Dưới đây là Danh sách các ký tự kết nối bằng Unicode. Bạn sẽ không tìm thấy chúng trên bàn phím của bạn.

U + 005F LINE Low _
U + 203F UNDERTIE ‿
U + 2040 CHARACTER TIE ⁀
U + 2054 INVERTED UNDERTIE ⁔
U + FE33 FORM
FORES FOR LINE
CHỨNG MINH ﹍
U + FE4E CENTRELINE LOW ĐƯỜNG DÂY ﹎
U + FE4F lượn sóng LOW ĐƯỜNG DÂY ﹏
U + FF3F fullwidth LOW ĐƯỜNG DÂY _


5
Tôi không biết bạn đang sử dụng bố cục bàn phím nào, nhưng tôi chắc chắn có thể gõ _ (U + 005F) đủ dễ dàng :)
bdonlan

4

Một ký tự kết nối được sử dụng để kết nối hai ký tự.

Trong Java, một ký tự kết nối là ký tự mà Character.getType (int codePoint) / Character.getType (char ch) trả về một giá trị bằng với Character.CONNECTOR_PUNCTUATION .

Lưu ý rằng trong Java, thông tin ký tự được dựa trên tiêu chuẩn Unicode xác định các ký tự kết nối bằng cách gán cho chúng loại Pc chung, là bí danh cho Trình kết nối .

Đoạn mã sau,

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

in các ký tự kết nối có thể được sử dụng để bắt đầu nhận dạng trên 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

Các biên dịch sau trên jdk1.6.0_45,

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

Rõ ràng, tuyên bố trên không thể biên dịch trên jdk1.7.0_80 & jdk1.8.0_51 cho hai ký tự kết nối sau (tương thích ngược ... rất tiếc !!!),

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

Dù sao, chi tiết sang một bên, kỳ thi chỉ tập trung vào bộ ký tự Latin cơ bản .

Ngoài ra, đối với các định danh pháp lý trong Java, thông số kỹ thuật được cung cấp ở đây . Sử dụng API lớp nhân vật để biết thêm chi tiết.


1

Một trong những ký tự vui nhộn nhất được cho phép trong các mã định danh Java (tuy nhiên không phải lúc bắt đầu) là ký tự unicode có tên "Zero Width Non Joiner" (& zwnj;, U + 200C, https://en.wikipedia.org / wiki / Zero-width_non-tham gia ).

Tôi đã có điều này một lần trong một đoạn XML bên trong một giá trị thuộc tính chứa tham chiếu đến một đoạn XML khác. Vì ZWNJ là "chiều rộng bằng không" nên không thể nhìn thấy (ngoại trừ khi đi cùng với con trỏ, nó được hiển thị ngay trên ký tự trước đó). Nó cũng không thể được nhìn thấy trong logfile và / hoặc đầu ra giao diện điều khiển. Nhưng nó đã ở đó mọi lúc: sao chép và dán vào các trường tìm kiếm và do đó không tìm thấy vị trí được giới thiệu. Nhập chuỗi (phần hiển thị của chuỗi) vào trường tìm kiếm tuy nhiên tìm thấy vị trí được tham chiếu. Mất một lúc để tìm hiểu điều này.

Nhập một Zero-Width-Non-Joiner thực sự khá dễ dàng (quá dễ) khi sử dụng bố cục bàn phím châu Âu, ít nhất là trong biến thể tiếng Đức của nó, ví dụ "Europatastatur 2.02" - có thể truy cập bằng AltGr + ".", Hai phím Thật không may, nằm ngay cạnh nhau trên hầu hết các bàn phím và có thể dễ dàng vô tình va vào nhau.

Quay lại với Java: Tôi nghĩ tốt, bạn có thể viết một số mã như thế này:

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

với cái thứ hai tôi được thêm vào bởi một người không tham gia có độ rộng bằng không (không thể làm điều đó trong đoạn mã trên được cắt trong trình soạn thảo của stackoverflow), nhưng điều đó không hiệu quả. IntelliJ (16.3.3) đã không khiếu nại, nhưng JavaC (Java 8) đã phàn nàn về một định danh đã được xác định - có vẻ như JavaC thực sự cho phép ký tự ZWNJ là một phần của mã định danh, nhưng khi sử dụng phản chiếu để xem nó làm gì, ZWNJ ký tự bị xóa khỏi định danh - thứ mà các ký tự như ‿ không.


0

Danh sách các ký tự mà bạn có thể sử dụng trong định danh của bạn (chứ không phải chỉ là lúc bắt đầu) là nhiều niềm vui hơn:

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

Danh sách này là:

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

Nó bao gồm hầu hết các nhân vật điều khiển! Tôi có nghĩa là chuông và shit! Bạn có thể làm cho mã nguồn của bạn rung chuông fn! Hoặc sử dụng các ký tự đôi khi sẽ chỉ được hiển thị, như dấu gạch nối mềm.


Nó bao gồm \ u007f, ký tự DEL. :-(
Todd O'Bryan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.