Apa itu "menghubungkan karakter" di pengidentifikasi Java?

208

Saya membaca untuk SCJP dan saya memiliki pertanyaan mengenai baris ini:

Pengidentifikasi harus dimulai dengan huruf, karakter mata uang ($), atau karakter penghubung seperti garis bawah (_). Pengidentifikasi tidak dapat memulai dengan angka!

Ini menyatakan bahwa nama pengidentifikasi yang valid dapat mulai dengan karakter penghubung seperti garis bawah. Saya pikir garis bawah adalah satu-satunya pilihan yang valid? Apa karakter penghubung lain yang ada?

Luke yang beruntung
sumber
2
Mengenai "karakter mata uang": pengunjung Inggris ke pertanyaan ini mungkin terkejut dan tertarik untuk mengetahui bahwa, sesuai dengan kemampuan untuk memulai dengan karakter mata uang "a", pengidentifikasi Java dapat, secara legal, mulai dengan simbol pound (£).
8bitjunkie
11
Perhatikan bahwa sejak Java 8, _adalah pengenal "usang". Secara khusus, kompiler memancarkan peringatan berikut: (penggunaan '_' sebagai pengidentifikasi mungkin tidak didukung dalam rilis setelah Java SE 8) .
aioobe
4
@aioobe Yup. Brian Goetz mengatakan mereka "mengklaim kembali" _untuk digunakan dalam fitur bahasa di masa depan . Pengidentifikasi yang mulai dengan garis bawah masih oke, tetapi garis bawah tunggal adalah kesalahan jika digunakan sebagai nama parameter lambda, dan peringatan di mana pun.
Boann
1
Untuk bytecode, apa pun berdasarkan urutan yang tidak mengandung . ; [ / < > :berjalan: stackoverflow.com/questions/26791204/… docs.oracle.com/javase/specs/jvms/se7/html/… Segala sesuatu yang lain adalah pembatasan khusus Java.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
@Boann Yang lucu adalah mereka melarang penggunaannya dalam lambdas, tetapi mungkin akan kembali sebagai pengenal "abaikan argumen ini", yang akan digunakan misalnya dalam lambdas. Aku hanya mencoba untuk menggunakannya seperti ini: _, _ -> doSomething();.
user31389

Jawaban:

268

Berikut adalah daftar karakter penghubung. Ini adalah karakter yang digunakan untuk menghubungkan kata-kata.

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

Ini mengkompilasi di Java 7.

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

Sebuah contoh. Dalam hal ini tpadalah nama kolom dan nilai untuk baris yang diberikan.

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

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

Pengikut

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

cetakan

$ _ ¢ £ ¤ ¥ ؋ ৲ ৳ ৻ ૱ ௹ ฿ ៛ ‿ ⁀ ⁔ ⁔ ₠ ₢ ₢ ₥ ₦ ₦ ₧ ₩ ₩ ₩ ₪ ₭ ₭ ₯ ₰ ₱ ₱ ₱ ₱ ₱ ₸ ₸ ₸ ₸ ₸ ﹏ ﹏ ﹏ ﹏ ﹏ ﹩ $ _ ¢ £ ¥ ₩

Peter Lawrey
sumber
109
Saya menantikan hari ketika saya mewarisi beberapa kode yang menggunakan pengidentifikasi ini!
Marko Topolnik
58
@MarkoTopolnik Berhati-hatilah dengan apa yang Anda inginkan. ;)
Peter Lawrey
3
BTW Anda dapat menggunakan simbol mata uang apa pun juga. int ৲, ¤, ₪₪₪₪;: D
Peter Lawrey
17
Saya mungkin melemparkan satu atau dua ini ke dalam kode saya, hanya untuk iseng! Dan untuk menguji apakah sistem build benar - benar memenuhi persyaratan UTF-8.
Marko Topolnik
82
@GrahamBorland Bagaimana if( ⁀ ‿ ⁀ == ⁀ ⁔ ⁀) atau if ($ == $)atau if (¢ + ¢== ₡)atauif (B + ︳!= ฿)
Peter Lawrey
25

beralihlah ke seluruh 65 ribu karakter dan tanyakan Character.isJavaIdentifierStart(c). Jawabannya adalah: "undertie" desimal 8255

Markus Mikkolainen
sumber
14
Saya tidak bisa menolak (dalam Scala): (1 to 65535).map(_.toChar).filter(Character.isJavaIdentifierStart).size- menghasilkan 48529 karakter ...
Tomasz Nurkiewicz
tampaknya ada beberapa karakter di dekat 65k dan 12k dan 8.5k dll.
Markus Mikkolainen
tidak menghasilkan jika Anda mengatakan "! IsLetter" dan "! isDigit"
Markus Mikkolainen
2546 + 2547 minimal "kotak gambar ..."
Markus Mikkolainen
3
Jumlah total = 90648, tapi saya akan Character.MAX_CODE_POINT, yang mungkin lebih dari 2<<16.
Martijn Courteaux
7

Spesifikasi pasti pengenal Java legal dapat ditemukan di Spesifikasi Bahasa Java .

Greg Hewgill
sumber
3
Saya tidak yakin benar-benar sepenuhnya menjawab pertanyaan (tersirat) karakter mana yang dapat memulai pengidentifikasi Java. Tautan berikut ini berakhir di Character.isJavaIdentifierStart () yang menyatakan karakter dapat memulai pengenal Java jika dan hanya jika salah satu dari kondisi berikut ini benar: ... ch adalah simbol mata uang ( seperti "$"); ch adalah karakter tanda baca yang menghubungkan ( seperti "_").
CVn
1
Tampaknya spesifikasi membiarkan daftar akhir karakter yang dapat diterima hingga implementasi, sehingga berpotensi berbeda untuk semua orang.
Greg Hewgill
3
@GregHewgill Itu akan bodoh, mengingat betapa ketatnya yang ditentukan semuanya. Saya pikir ini adalah kelas karakter Unicode aktual, yang didefinisikan (di mana lagi?) Dalam standar Unicode. isJavaIdentifierStart () menyebutkan getType (), dan simbol mata uang dan tanda baca konektor keduanya juga tipe yang dapat dikembalikan oleh fungsi itu, sehingga daftar mungkin diberikan di sana. "Kategori umum" sebenarnya adalah istilah khusus dalam standar Unicode. Jadi nilai yang valid akan L[semua], Nl, Sc, Pc.
Random832
3
@GregHewgill benar. Spesifikasi pendek dan jelas, dan itu didefinisikan oleh Character.isJavaIdentifierStart () dan Character.isJavaIdentifierPart (). Tamat. Hal utama yang perlu diingat adalah bahwa Unicode berkembang; jangan jatuh ke dalam perangkap berpikir set karakter sebagai selesai (Latin adalah contoh yang mengerikan; abaikan saja). Karakter dibuat sepanjang waktu. Tanyakan teman-teman Jepang Anda. Harapkan pengidentifikasi java legal berubah seiring waktu - dan itu disengaja. Intinya adalah membiarkan orang menulis kode dalam bahasa manusia. Itu mengarah pada persyaratan sulit untuk memungkinkan perubahan.
James Moore
6

Berikut adalah Daftar Karakter konektor di Unicode. Anda tidak akan menemukannya di keyboard Anda.

U + 005F LOW GARIS _
U + 203F UNDERTIE ‿
U + 2040 KARAKTER TIE ⁀
U + 2054 TERBALIK UNDERTIE ⁔
U + FE33 PRESENTASI FORMULIR VERTICAL RENDAH GARIS _ U
+ FE34 PRESENTASI FORMULIR VERTICAL bergelombang RENDAH GARIS ︴
U + FE4D putus-putus RENDAH GARIS ﹍
U + FE4E CENTRELINE LOW LINE ﹎
U + FE4F WAVY LOW LINE ﹏
U + FF3F FULLWIDTH LOW LINE INE

Tiruan
sumber
5
Saya tidak tahu apa tata letak keyboard yang Anda gunakan, tapi saya pasti bisa mengetik _ (U + 005F) dengan cukup mudah :)
bdonlan
4

Karakter penghubung digunakan untuk menghubungkan dua karakter.

Di Jawa, karakter penghubung adalah karakter yang Character.getType (int codePoint) / Character.getType (char ch) menghasilkan nilai yang sama dengan Character.CONNECTOR_PUNCTUATION .

Perhatikan bahwa di Jawa, informasi karakter didasarkan pada standar Unicode yang mengidentifikasi karakter penghubung dengan menetapkannya kategori umum Pc, yang merupakan alias untuk Connector_Punctuation .

Cuplikan kode berikut,

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

mencetak karakter penghubung yang dapat digunakan untuk memulai pengidentifikasi pada 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

Kompilasi berikut pada jdk1.6.0_45,

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

Rupanya, deklarasi di atas gagal dikompilasi pada jdk1.7.0_80 & jdk1.8.0_51 untuk dua karakter penghubung berikut (kompatibilitas mundur ... oops !!!),

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

Pokoknya, selain detail, ujian hanya berfokus pada rangkaian karakter Basic Latin .

Juga, untuk pengidentifikasi hukum di Jawa, spesifikasi disediakan di sini . Gunakan API kelas Karakter untuk mendapatkan detail lebih lanjut.

sxnamit
sumber
1

Salah satu karakter paling menyenangkan yang diizinkan di pengidentifikasi Java (namun tidak di awal) adalah karakter unicode bernama "Zero Width Non Joiner" (& zwnj ;, U + 200C, https://en.wikipedia.org / wiki / Zero-width_non-joiner ).

Saya punya ini sekali dalam sepotong XML di dalam nilai atribut memegang referensi ke bagian lain dari XML itu. Karena ZWNJ adalah "lebar nol" tidak dapat dilihat (kecuali ketika berjalan bersama dengan kursor, itu ditampilkan tepat pada karakter sebelumnya). Itu juga tidak bisa dilihat di logfile dan / atau keluaran konsol. Tapi itu ada di sana sepanjang waktu: salin & tempel ke bidang pencarian dan karenanya tidak menemukan posisi yang dimaksud. Mengetik (terlihat bagian dari) string ke dalam kolom pencarian namun menemukan posisi yang dimaksud. Butuh waktu beberapa saat untuk memikirkan ini.

Mengetik Zero-Width-Non-Joiner sebenarnya cukup mudah (terlalu mudah) saat menggunakan tata letak keyboard Eropa, setidaknya dalam varian Jerman, misalnya "Europatastatur 2.02" - dapat dicapai dengan AltGr + ".", Dua kunci yang sayangnya terletak tepat di sebelah satu sama lain di sebagian besar keyboard dan dapat dengan mudah disatukan secara tidak sengaja.

Kembali ke Jawa: Saya pikir baik, Anda bisa menulis beberapa kode seperti ini:

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

dengan yang kedua saya tambahkan oleh zero-width-non-joiner (tidak bisa melakukan itu dalam kode di atas terpotong di editor stackoverflow), tetapi itu tidak berhasil. IntelliJ (16.3.3) tidak mengeluh, tetapi JavaC (Java 8) memang mengeluh tentang pengidentifikasi yang sudah didefinisikan - tampaknya JavaC benar-benar memungkinkan karakter ZWNJ sebagai bagian dari pengidentifikasi, tetapi ketika menggunakan refleksi untuk melihat apa yang dilakukannya, ZWNJ karakter dilucuti dari pengidentifikasi - sesuatu yang karakter seperti ‿ tidak.

Ulrich Grepel
sumber
0

Daftar karakter yang dapat Anda gunakan di dalam pengidentifikasi Anda (bukan hanya di awal) jauh lebih menyenangkan:

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

Daftarnya adalah:

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

Ini mencakup sebagian besar karakter kontrol! Maksudku lonceng dan omong kosong! Anda dapat membuat kode sumber Anda membunyikan bel fn! Atau gunakan karakter yang hanya akan ditampilkan kadang-kadang, seperti tanda hubung lunak.

Aleksandr Dubinsky
sumber
Ini termasuk \ u007f, karakter DEL. :-(
Todd O'Bryan