2013-05-12 14 views
23

In base a this table of Java operator precedence and associativity, l'accesso membro ha precedenza più elevata rispetto all'operatore new.Chiamare un metodo su un nuovo oggetto in Java senza parentesi: violazione dell'ordine delle operazioni?

Tuttavia, data una classe myClass e una funzione di membro non statica myFunction, la seguente riga di codice è valido:

new myClass().myFunction();

Se . viene valutata prima new, come può essere eseguito questa linea? In altre parole, perché non sono necessarie le parentesi?

(new myClass()).myFunction();

La mia ipotesi è che, poiché () condivide la precedenza con ., il myClass() viene valutata prima, e così il compilatore sa ancora prima di valutare la parola chiave new che il costruttore myClass con i parametri a zero viene chiamato. Tuttavia, questo sembra ancora implicare che la prima riga dovrebbe essere identica a new (myClass().myFunction());, che è non il caso.

+3

Questa tabella non è un riferimento normativo. Non puoi citarlo come prova. – EJP

+0

@EJP Bene, mi rendo conto che non è perfetto, ma sembrava sufficientemente affidabile. Altre tabelle di precedenza sembrano indicare la stessa cosa o tralasciare del tutto. –

+0

Non puoi averlo in entrambi i modi. O è perfetto e affidabile al 100% o non lo puoi citare come prova. Il fatto che non sia normativo significa che non è affidabile al 100% * ipso facto. Lo stesso vale per "altre tabelle di precedenza", incluso di fatto quello nel tutorial di Java. L'unico riferimento normativo è [Java Language Specification, Chapter 18] (http://docs.oracle.com/javase/specs/jls/se7/html/jls-18.html). – EJP

risposta

32

Ciò è dovuto al modo in cui è definito il grammar linguaggio Java. La precisione degli operatori entra in gioco proprio quando la stessa sequenza lessicale può essere analizzata in due modi diversi, ma questo non è il caso.

Perché?

Poiché l'allocazione viene definita in:

Primary: 
    ... 
    new Creator 

mentre il metodo di chiamata è definito in:

Selector: 
    . Identifier [Arguments] 
    ... 

ed entrambi sono utilizzati qui:

Expression3: 
    ... 
    Primary { Selector } { PostfixOp } 

così accade che

new myClass().myFunction(); 

viene analizzato come

  Expression 
      | 
      | 
    ---------+-------- 
    |    | 
    |    | 
    Primary  Selector 
    |    | 
    |    | 
---+---   ... 
|  | 
new Creator 

Quindi non c'è scelta in base alla priorità, perché il Primary viene ridotta prima. Presente che per la particolare situazione come

new OuterClass.InnerClass() 

il nome della classe è in realtà analizzato prima che l'operatore new e ci sono regole per gestire questo caso davvero. Controlla la grammatica se ti piace vederli.

+0

Bella risposta. Grazie per gli schemi! – Andbdrew

+0

Ottima risposta. Molte grazie. –

1

Non sono d'accordo con la conclusione tratta dal diagramma di Jack. Quando una grammatica è scritta, i suoi non terminali e la struttura sono progettati per implementare la precedenza e l'associatività della lingua descritta. Ecco perché il classico BNF per le espressioni introduce il "termine" e il "fattore" non-terminale - per applicare la normale moltiplicazione prima dell'aggiunta della precedenza dell'aritmetica.

Quindi il fatto che "Primario -> nuovo Creatore" e "Espressione -> Selettore principale" nella grammatica significhi che "nuovo Creatore" è a un livello di precedenza più alto di "Selettore primario".

Mi sembra che la grammatica sia la prova che la tabella di precedenza e associatività dell'operatore Java non è corretta.

+0

Sembra che la premessa specifica della risposta di Jack con cui non si condivide quanto detto sia "La precisione degli operatori entra in gioco proprio quando la stessa sequenza lessicale può essere analizzata in due modi diversi".E infatti alcune grammatiche possono essere ambigue per quanto riguarda l'ordine delle operazioni, e possono avere una tabella di precedenza * oltre a * la specifica grammaticale stessa. –

+0

Ma sembra che tu abbia ragione che questo * non * sia il caso per Java, perché [Capitolo 15 della specifica] (https://docs.oracle.com/javase/specs/jls/se8/html/jls- 15.html) dice: "La precedenza tra gli operatori è gestita da una gerarchia di produzioni grammaticali: l'operatore con la precedenza più bassa è la freccia di un'espressione lambda (->), seguita dagli operatori di assegnazione". La tua risposta sarebbe migliorata citando questa citazione come prova. –

+0

(Mi rendo conto che questa citazione proviene da una nuova versione delle specifiche, dal momento che quando ho fatto questa domanda lambdas non era ancora stato introdotto in Java.) –

Problemi correlati