Warum können einige ASCII-Zeichen im Java-Quellcode nicht in der Form ‘\uXXXX’ ausgedrückt werden?

Lesezeit: 3 Minuten

Benutzer-Avatar
Durandal

Darüber bin ich heute (wieder) gestolpert:

class Test {
    char ok = '\n';
    char okAsWell="\u000B";
    char error="\u000A";
}

Es kompiliert nicht:

Ungültige Zeichenkonstante in Zeile 4.

Der Compiler scheint darauf zu bestehen, dass ich stattdessen ‘\n’ schreibe. Ich sehe keinen Grund dafür, aber es ist sehr ärgerlich.

Gibt es eine logische Erklärung, warum Zeichen mit einer speziellen Notation (wie \t, \n, \r) muss in dieser Form im Java-Quellcode ausgedrückt werden?

  • Sie können alle Quellen in Ihrem Code durch ersetzen \uXXXX Sequenzen, um es unlesbar zu machen, aber es wird gut kompiliert, da es alle diese vor dem Kompilieren in den Text konvertiert.

    – Peter Lawrey

    7. März 2013 um 18:09 Uhr

Benutzer-Avatar
Assyrien

Unicode-Zeichen werden durch ihren Wert ersetzt, sodass Ihre Zeile vom Compiler ersetzt wird durch:

char error="
";

was keine gültige Java-Anweisung ist.

Dies wird von der diktiert Sprachspezifikation:

Ein Compiler für die Programmiersprache Java (“Java-Compiler”) erkennt zuerst Unicode-Escapes in seiner Eingabe und übersetzt die ASCII-Zeichen \u gefolgt von vier Hexadezimalziffern in die UTF-16-Codeeinheit (§3.1) des angegebenen Hexadezimalwerts und alle anderen Zeichen unverändert weitergeben. Die Darstellung ergänzender Zeichen erfordert zwei aufeinanderfolgende Unicode-Escapezeichen. Dieser Übersetzungsschritt führt zu einer Folge von Unicode-Eingabezeichen.

Dies kann zu überraschenden Dingen führen, zum Beispiel ist dies ein gültiges Java-Programm (es enthält versteckte Unicode-Zeichen) – Mit freundlicher Genehmigung von Peter Lawrey:

public static void main(String[] args) {
    for (char c‮h = 0; c‮h < Character.MAX_VALUE; c‮h++) {
        if (Character.isJavaIdentifierPart(c‮h) && !Character.isJavaIdentifierStart(c‮h)) {
            System.out.printf("%04x <%s>%n", (int) c‮h, "" + c‮h);
        }
    }
}

  • +1 Gut zu wissen. Also wenn ich benutze System.out.print("Hello ");//\u000ASystem.out.println("World"); es druckt “Hello World”, auch wenn der zweite Druck theoretisch im Kommentar steht: D

    – Pschemo

    7. März 2013 um 16:20 Uhr


  • Du warst der Erste, glaube ich, also habe ich diesen akzeptiert 🙂 Obwohl das die Ursache dahinter perfekt erklärt, bin ich immer noch neugierig, warum die Sprachschöpfer dachten, dass eine frühe Erweiterung eine gute Idee sei. Es kommt mir immer noch wie ein großer WTF vor.

    – Durandal

    7. März 2013 um 16:24 Uhr

  • @Durandal Dadurch können Sie Zeichen verwenden, die im Zeichensatz der Quelldatei nicht dargestellt werden können (nicht, dass mir das jemals passiert wäre!).

    – Assylias

    8. März 2013 um 12:18 Uhr

Benutzer-Avatar
poitroae

Unicode-Escape-Sequenzen wie \u000a werden ersetzt durch die tatsächlichen Zeichen, die sie darstellen, bevor der Java-Compiler irgendetwas anderes mit dem Quellcode macht. Und so endet Ihr Programm schließlich bei

char ch="
";

Also die \u000a in Ihrem Quellcode wird intern durch ein Zeilenvorschubzeichen ersetzt. Beachten Sie, dass dies geschieht, bevor der Compiler Ihren Quellcode tatsächlich liest und interpretiert.

In Bezug auf Java-Sprachspezifikation:

Es ist ein Kompilierzeitfehler für a Zeilenabschluss (§3.4) nach dem Öffnen ‘ und vor dem Schließen ‘ erscheinen.

Und alle wissen es auswendig, \n ist ein ZeilenabschlussZitat:

 LineTerminator:
    the ASCII LF character, also known as "newline"
    the ASCII CR character, also known as "return"
    the ASCII CR character followed by the ASCII LF character

Andere Symbole, die Probleme verursachen könnten, sind \, ' und " zum Beispiel.

  • Wie sieht das Programm aus?

    – Wallyk

    7. März 2013 um 16:16 Uhr

  • Es scheint viel mehr als 3: \u0027 (‘) \u005c (\) zu geben, die ebenfalls Chaos anrichten. \u0034 (“) unterbricht String-Literale.

    – Durandal

    7. März 2013 um 16:47 Uhr


Ich denke, der Grund ist das \uXXXX Sequenzen werden expandiert, wenn der Code geparst wird, siehe JLS §3.2. Lexikalische Übersetzungen.

Benutzer-Avatar
Evgeniy Dorofeev

Es ist in 3.3 beschrieben. Unicode-Escapes http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html. Javac findet zuerst \uxxxx-Sequenzen in .java und ersetzt sie durch echte Zeichen und kompiliert dann. Im Falle von

char error="\u000A";

\u000A wird durch ersetzt newline Zeichencode (10) und der eigentliche Text werden

char error="
";

Weil der Compiler sie genauso behandelt wie Text ohne Escapezeichen.

Dies ist ein gültiger Code:

 class \u00C9 {}

1031350cookie-checkWarum können einige ASCII-Zeichen im Java-Quellcode nicht in der Form ‘\uXXXX’ ausgedrückt werden?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy