2015-08-18 17 views
7

Dato il seguente pezzo valida di codice:istruzioni Java, l'elaborazione di precedenza ("penzoloni altro")

Boolean a = false; 

if (a) 
    System.out.println("A"); 
else 
    System.out.println("!A"); 

Ora, in base alla documentazione if tra cui sua condizione ed interna statement è anche un statement (https://docs.oracle.com/javase/tutorial/java/nutsandbolts/if.html - a almeno si chiama if-statement tutta la documentazione)

ad esempio:

if (b){ 
     System.out.println("B"); 
    } 

è un statement.

Tuttavia, quando sostituiremo una dichiarazione esistente con un'altra, non dovrebbe toccare la logica generale, giusto? Supponendo che si sostituisce la (Expression) - statement con l'if-statement sopra:

Boolean a = false; 
Boolean b = false: 

if (a) 
    if (b){ 
     System.out.println("A and B"); 
    } 
else 
    System.out.println("!A"); 

Java Compiler interpreterà l'esempio di codice nel modo seguente (tra parentesi graffe completo per visualizzare la spiegazione):

Boolean a = false; 
Boolean b = false: 

if (a){ 
    if (b){ 
     System.out.println("A nad B"); 
    } else { 
     System.out.println("!A"); 
    } 
} 

che non è la logica iniziale .

Quindi perché si scambia una dichiarazione con un'altra che modifica la logica?

Dall'esempio si può chiaramente dire che il problema è solo il parentesi, ma non riesco a trovare le informazioni sul modo in cui Java è esattamente a che fare con questo, se parentesi graffe sono ommited.

Quindi sono interessato solo se c'è qualcosa di scritto su questo comportamento? Perché java preferisce collegare lo else al più recente if, anziché il primo if che incontra durante l'analisi?

+0

Se il collegamento è l'altro per la prima 'if', che cosa accadrà se c'è un'altra cosa di sotto di essa? – Codebender

+0

L'istruzione che hai citato da ORACLE probabilmente si applica solo quando vengono utilizzate le parentesi. – Elbek

+0

Questa è un'area comune di ambiguità. [Wikipedia Dangling altro articolo.] (Https://en.wikipedia.org/wiki/Dangling_else) Hai detto "quale non è la logica iniziale". nella tua domanda, ma la cosa è che secondo il compilatore Java era * la logica iniziale. Se Java fosse come Python in quanto riguardava l'indentazione, sarebbe stato in grado di distinguere come ci si aspettava perché il 'else' era sullo stesso livello del primo' if', ma far rientrare il rientro è effettivamente lo stesso di far rispettare il uso di parentesi graffe. –

risposta

7

Ovviamente, la risposta è nello Java Language Specification. La sezione rilevante è section 14.5, "Statements", che descrive esattamente questo caso:

Come in C e C++, l'istruzione if del linguaggio di programmazione Java soffre della cosiddetta "penzoloni else problema", illustrato da questo esempio fuorviante formattato :

if (door.isOpen()) 
    if (resident.isVisible()) 
     resident.greet("Hello!"); 
else door.bell.ring(); // A "dangling else" 

il problema è che sia il esterna if dichiarazione e l'interno if affermazione potrebbe plausibilmente possedere la clausola else. In questo esempio, si potrebbe supporre che il programmatore intendesse la clausola else appartenere all'istruzione esterna if.

E infine:

Il linguaggio di programmazione Java, come C e C++ e molti linguaggi di programmazione prima di loro, decreta arbitrariamente una clausola else appartiene alla più interno if a cui si potrebbe forse appartengono a.

(enfasi da me)

+0

Thx per la tua risposta. Penso che questo sia abbastanza ovvio quando si guarda all'esempio completo, ma prendere l'istruzione * replace con statement * idea non è proprio quello che fa il compilatore - perché è un ofc. non si preoccupa dell'assegnazione * prima * di 'else'. (Beh, questo è il motivo per cui uso sempre le parentesi graffe, l'ho appena incontrato a causa della pigrizia su qualche codice veloce) – dognose

0

Funziona come previsto, la tua indentazione non significa nulla. else si riferisce al più vicino in caso affermativo si riferisce a if(b) Dovresti aver indended il codice:

Boolean a = false; 
Boolean b = false: 

if (a) 
    if (b){ 
     System.out.println("A and B"); 
    } else 
     System.out.println("!A"); 

Ma in generale è sempre buona norma utilizzare le parentesi {}

+2

la domanda riguardava la documentazione – zec

-3

Java è un linguaggio orientato agli oggetti che essenzialmente significa che segue l'approccio bottom-up durante la compilazione del codice. Ecco perché considera l'ultima dichiarazione if come il compagno di un'altra parte.

0

Questo è il comportamento corretto. Se dopo un'istruzione if, non ci sono parentesi graffe, solo la prima istruzione viene considerata parte della condizione vera. Il problema con l'esempio è che non ci sono parentesi graffe per definire l'ambito delle istruzioni e c'è un parentesi graffa subito dopo la valutazione della condizione b.

Dopo la prima istruzione if, la seconda istruzione if utilizza una parentesi graffa e stabilisce la precedenza delle istruzioni.Si dovrebbe usare il codice come questo: -

Boolean a = false; 
Boolean b = false: 

    if (a){ 
     if (b) 
      System.out.println("A and B"); 
    } 
    else 
     System.out.println("!A"); 
1

Avendo esso associare con il più recente if sai che solo bisogno di leggere il più recente if a capire la logica. Altrimenti avresti letto tutte le if e tutte le clausole else per comprenderne qualcuna.

Dire che non hai fatto il più recente se, ma meno recente, if.

if (a) 
    if (b) 
    something(); 
    else // if this is else to if (a) 
    something(); 
else if (c) // what is this the else to? 
    something(); 
else 
    something(); 

Quando si dispone di più il resto clausole, è molto più facile da leggere se il resto è per il più recente if

+0

Questo è vero (e documentato nel JLS, vedere la risposta da @ Marco13) – dognose

0

Il DOM di un programma Java, chiamato AST, albero di sintassi astratta, è una struttura più pura, e in generale usata come base per parlare anche del significato, della semantica, del codice.

Il testo lineare ha molti parsing carenze, come:

-(-y) equal to y for most int values 
--y 

Il penzolante else è un punto.

Nell'informatica solo i linguaggi dichiarativi (funzioni logiche) vengono talvolta trattati a livello simbolico. C/C++ d'altra parte è notoriamente contestuale.

2

Se sei veramente interessato a sapere tutto quello che c'è da sapere su Java, lo Java Specifications è uno strumento prezioso. La sezione 2 sarebbe di tuo interesse e la tua domanda.

+0

Thx per il collegamento, cercava questo, ma non riusciva a ricordare il nome. Vedremo se c'è qualcosa di dettagliato in là :-) – dognose

+1

Anche come [Marco13] (http://stackoverflow.com/users/3182664/marco13) ha sottolineato in un commento sulla domanda principale, [sezione 14.5] (https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.5) è molto pertinente, dando lo stesso esempio (con diverse espressioni booleane e quindi affermazioni ovviamente) –

+0

Grazie Cap I ero solo pigro. :/ – zec

Problemi correlati