2013-03-07 10 views
57

ci siamo imbattuti su questo (ancora una volta) di oggi:Perché alcuni caratteri ASCII non possono essere espressi nel formato ' uXXXX' nel codice sorgente Java?

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

non si compila:

costante carattere non valido in linea 4.

Il compilatore sembra insistere che scrivo '\ n' invece. Non vedo alcuna ragione per questo, ma è molto fastidioso.

C'è una spiegazione logica per cui caratteri che hanno una notazione speciale (come \t, \n, \r) devono essere espressi in quella forma in sorgente di Java?

+1

è possibile sostituire tutta la fonte nel codice con '\ uXXXX' sequenze a renderlo illeggibile, ma verrà compilato correttamente convertendolo in testo prima della compilazione. –

risposta

85

caratteri Unicode sono sostituite dal loro valore, quindi la vostra linea è sostituito dal compilatore con:

char error = ' 
'; 

, che non è una dichiarazione di Java valida.

Questo è dettata dal Language Specification:

un compilatore per il linguaggio di programmazione Java ("compilatore Java") prima riconosce Unicode sfugge nel suo ingresso, traducendo i caratteri ASCII \ u seguita da quattro cifre esadecimali a l'unità di codice UTF-16 (§3.1) del valore esadecimale indicato e passando tutti gli altri caratteri invariati. La rappresentazione di caratteri supplementari richiede due escape Unicode consecutivi. Questo passaggio di traduzione genera una sequenza di caratteri di input Unicode.

Questo può portare a cose sorprendenti, ad esempio, si tratta di un programma Java valido (che contiene caratteri Unicode nascosti) - courtesy of 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); 
     } 
    } 
} 
+16

+1 Buono a sapersi. Quindi se uso 'System.out.print (" Hello "); // \ u000ASystem.out.println (" Mondo ");' stampa "Hello World" anche se la seconda stampa è teoreticamente in commento: D – Pshemo

+5

+1 conoscenza impressionante, mi hai insegnato qualcosa di nuovo oggi! –

+7

Sei stato il primo, credo, quindi ho accettato questo :) Anche se questo spiega perfettamente la causa, sono ancora curioso di sapere perché i creatori del linguaggio pensavano che la prima espansione fosse una buona idea. Mi sembra ancora un grande WTF. – Durandal

23

sequenze di escape Unicode come \u000a vengono sostituiti dal i personaggi reali che rappresentano prima che il compilatore Java faccia qualsiasi altra cosa con il codice sorgente. E così, il programma alla fine finisce in

char ch = ' 
'; 

Così il \u000a nel codice sorgente è sostituito internamente da un carattere di avanzamento riga. Nota che ciò accade prima che il compilatore legga effettivamente e interpreti il ​​tuo codice sorgente.

riferendosi al Java Language Specification:

È un errore di compilazione di una terminazione di linea (§3.4) a comparire dopo l'apertura 'e prima della chiusura'.

E così tutti sanno a memoria, \n è un line terminator, citando:

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 

Altri simboli che possono dare problemi sono \, ' e " per esempio.

+1

Il programma sembra che cosa? – wallyk

+0

Sembra che ci sia molto più di 3: \ u0027 (') \ u005c (\\) crea anche scompiglio. \ u0034 (") interrompe i valori letterali stringa. – Durandal

2

Poiché il compilatore li tratta come testo senza escape.

Questo è codice valido:

class \u00C9 {} 
4

È descritto in 3.3. Unicode Escapes http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html. Javac dapprima trova le sequenze \ uxxxx in .java e le sostituisce con caratteri reali, quindi le compila. In caso di

char error = '\u000A'; 

\ u000A sara 'sostituito con newline codice carattere (10) e il testo vero e proprio sarà

char error = ' 
'; 
Problemi correlati