Що таке "з'єднувальні символи" в ідентифікаторах Java?


208

Я читаю за SCJP, і у мене є питання щодо цього рядка:

Ідентифікатори повинні починатися з літери, символу валюти ($) або сполучного символу, такого як підкреслення (_). Ідентифікатори не можуть починатися з числа!

У ньому йдеться про те, що дійсне ім'я ідентифікатора може починатися із сполучного символу, такого як підкреслення. Я думав, що підкреслення - єдиний вірний варіант? Які ще сполучні символи є?


2
Щодо "символу валюти": відвідувачі Великобританії з цим питанням можуть здивуватися та зацікавлені знати, що, відповідно до того, що можна починати з символу валюти "", ідентифікатори Java можуть юридично починатись із символу фунта (£).
8bitjunkie

11
Зауважте, що оскільки Java 8 _є "застарілим" ідентифікатором. Зокрема, компілятор видає таке попередження: (використання "_" як ідентифікатора може не підтримуватися у випусках після Java SE 8) .
aioobe

4
@aioobe Yup Брайан Гец каже, що вони "вимагають" _для використання в майбутніх мовних функціях . Ідентифікатори, які починаються з підкреслення, все одно добре, але окремий підкреслення - це помилка, якщо він використовується як ім'я параметра лямбда та попередження скрізь.
Боан

1
Для байткод, нічого по послідовності , яка не містить . ; [ / < > :йде: stackoverflow.com/questions/26791204 / ... docs.oracle.com/javase/specs/jvms/se7/html / ... Все інше є Java-єдине обмеження.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

@Boann Найсмішніше те, що вони забороняють його використання в лямбдах, але це, ймовірно, повернеться як ідентифікатор "ігнорувати цей аргумент", який буде використовуватися, наприклад, в лямбдах. Я просто намагався використовувати його як це: _, _ -> doSomething();.
користувач31389

Відповіді:


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
Я з нетерпінням чекаю дня, коли я успадкую якийсь код, який використовує ці ідентифікатори!
Марко Тополник

58
@MarkoTopolnik Будь уважним, що ти хочеш. ;)
Пітер Лорі

3
BTW Ви також можете використовувати будь-який із символів валюти. int ৲, ¤, ₪₪₪₪;: D
Пітер Лорі

17
Я можу кинути один або два з них у свій код, лише для ударів! І перевірити, чи справді система збірки відповідає сумісності UTF-8.
Марко Тополник

82
@GrahamBorland Як щодо if( ⁀ ‿ ⁀ == ⁀ ⁔ ⁀) або if ($ == $)або if (¢ + ¢== ₡)абоif (B + ︳!= ฿)
Пітер Lawrey

25

повторіть цілі 65k символів і запитайте Character.isJavaIdentifierStart(c). Відповідь: "нижня частина" десяткової 8255


14
Я не міг протистояти (у Скалі): (1 to 65535).map(_.toChar).filter(Character.isJavaIdentifierStart).size- дає 48529 символів ...
Томаш Нуркевич

Мабуть, є кілька символів біля 65k, 12k та 8.5k тощо.
Markus Mikkolainen

не поступається, якщо ви говорите "! isLetter" і "! isDigit"
Маркус Міколайнен

2546 + 2547 принаймні "малювання коробки ..."
Маркус Міколайнен

3
Загальна кількість = 90648, але я збираюся Character.MAX_CODE_POINT, що, мабуть, більше 2<<16.
Мартійн Курто

7

Остаточну специфікацію юридичного ідентифікатора Java можна знайти в специфікації мови Java .


3
Я не впевнений, що насправді повністю відповідає на (мається на увазі) питання про те, які символи можуть запустити ідентифікатор Java. За наступними посиланнями ми опиняємось у Character.isJavaIdentifierStart (), який зазначає, що персонаж може запустити ідентифікатор Java, якщо і лише за умови виконання однієї з таких умов: ... ch - символ валюти ( наприклад, "$"); ch - сполучний розділовий знак ( наприклад, "_").
CVn

1
Здається, що специфікація залишає остаточний список прийнятних символів аж до реалізації, тому потенційно вона може бути різною для всіх.
Грег Хьюгілл

3
@GregHewgill Це було б нерозумно, враховуючи, наскільки чітко визначено все інше. Я думаю, що це фактичні класи символів Unicode, які визначені (де ще?) У стандарті Unicode. isJavaIdentifierStart () згадує getType (), а символ валюти та розділові знаки сполучення - це також типи, які можуть бути повернуті цією функцією, тому списки можуть бути надані там. "Загальна категорія" насправді є специфічним терміном у стандарті Unicode. Таким чином, допустимі значення були б L[все] Nl, Sc, Pc.
Випадково832

3
@GregHewgill правильний. Специфікація коротка і чітка, її визначають Character.isJavaIdentifierStart () та Character.isJavaIdentifierPart (). Кінець. Ключове, що потрібно пам’ятати, - це те, що Unicode розвивається; не потрапляйте в пастку мислення наборів персонажів як закінчених (латина - жахливий приклад; ігноруйте це). Персонажі створюються постійно. Попросіть своїх японських друзів. Очікуйте, що юридичні ідентифікатори Java зміниться з часом - і це навмисно. Сенс у тому, щоб люди могли писати код людськими мовами. Це призводить до жорсткої вимоги щодо дозволу змін.
Джеймс Мур

6

Ось список символів з'єднувачів у Unicode. Ви їх не знайдете на своїй клавіатурі.

U + 005F LOW ЛІНІЯ _
U + 203F UNDERTIE ‿
U + 2040 ХАРАКТЕРУ TIE ⁀
U +2054 INVERTED UNDERTIE ⁔
U + FE33 ПРЕЗЕНТАЦІЯ ФОРМА ДЛЯ вертикально НИЗЬКИЙ ЛІНІЯ _ U
+ FE34 ПРЕЗЕНТАЦІЇ ФОРМИ ДЛЯ ВЕРТИКАЛЬНОЇ хвилясті НИЗКОЮ ЛІНІЯ ︴
U + FE4D пунктирними LOW ЛІНІЯ CENT
U + FE4E ЦЕНТРАЛЬНА НИЗЬКА ЛІНІЯ ﹎
U + FE4F ХВИЛЬНА НИЗЬКА ЛІНІЯ ﹏
U + FF3F ПОЛІВНІ ЛІНІ _


5
Я не знаю, яку клавіатуру ви використовуєте, але я, безумовно, можу набрати _ (U + 005F) досить легко :)
bdonlan

4

Для з'єднання двох символів використовується сполучний символ.

В Java, з'єднувальний символ є той , для якого Character.getType (интермедиат елемент коду) / Character.getType (символ ч) повертає значення , рівне 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

У будь-якому випадку, деталі в стороні, іспит зосереджується лише на базовому наборі символів латинської мови .

Також для юридичних ідентифікаторів на Java специфікація надана тут . Щоб отримати докладніші відомості, використовуйте API класів символів.


1

Одним з найбільш цікавих персонажів, дозволених в ідентифікаторах Java (однак не на старті), є символ унікоду з назвою "Zero Width Non Joiner" (& zwnj ;, U + 200C, https://en.wikipedia.org / wiki / Zero-width_non-joiner ).

Я мав це один раз у фрагменті XML всередині значення атрибута, що містить посилання на інший фрагмент цього XML. Оскільки ZWNJ "нульової ширини", його не видно (за винятком випадків, коли ви ходите разом з курсором, він раніше відображається прямо на символі). Його також не можна було побачити у вихідному файлі та / або консолі. Але він був там увесь час: скопіюйте та вставте в пошукові поля, отримавши це, і, отже, не знайшли згадане місце Набравши (видиму частину) рядка в поле пошуку, проте знайшлося згадане положення. Мені потрібен час, щоб зрозуміти це.

Введення Zero-Width-Non-Joiner насправді досить легко (занадто просто) при використанні європейської розкладки клавіатури, принаймні в її німецькому варіанті, наприклад, "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!

Він включає більшість контрольних символів! Я маю на увазі дзвони і лайно! Ви можете змусити ваш вихідний код дзвонити у дзвінок fn! Або використовуйте символи, які відображатимуться лише іноді, як м'який дефіс.


Він включає \ u007f символ DEL. :-(
Тодд О'Бріан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.