2014-04-11 9 views
9

In Eclipse Keplero 4.2 con JDK 1.7 ottengo seguente errore in Eclipse:Eclipse non riesce a compilare il codice generico, ma mvn compilazione funziona

The method or(capture#2-of ?) in the type Optional<capture#2-of ?> is not applicable for the arguments (Object)

mentre si compila con successo durante l'esecuzione mvn compile.

I classe sguardi seguenti:

package testit; 

import java.util.Map; 
import java.util.Map.Entry; 

import com.google.common.base.Optional; 

public class Test { 

    private static final Object NO_VALUE = new Object(); 

    public void method(Map<String, ?> map) { 
     for (Entry<String, ?> entry : map.entrySet()) { 
      Optional.fromNullable(entry.getValue()).or(NO_VALUE); 
//             ^^ error here 
     } 
    } 
} 

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 
    <groupId>my.test</groupId> 
    <artifactId>testit</artifactId> 
    <version>0.0.1-SNAPSHOT</version> 
    <dependencies> 
     <dependency> 
      <groupId>com.google.guava</groupId> 
      <artifactId>guava</artifactId> 
      <version>13.0.1</version> 
     </dependency> 
    </dependencies> 
    <build> 
    <plugins> 
      <plugin> 
       <groupId>org.apache.maven.plugins</groupId> 
       <artifactId>maven-compiler-plugin</artifactId> 
       <version>3.1</version> 
       <configuration> 
        <source>1.7</source> 
        <target>1.7</target> 
       </configuration> 
      </plugin>  
    </plugins> 
    </build> 
</project> 

Il codice simile viene eseguito su produzione per un lungo tempo senza errori (in questo settore). Si sta compilando in Maven, Jenkins, Intelij ma non in Eclipse. La domanda è: perché non si compila in Eclipse?

+1

+1 Confermato anche qui. Ben fatto per fornire un buon esempio di codice nella tua domanda. È interessante notare che il Maven incorporato in Eclipse può anche costruirlo. –

+0

Puoi verificare se le impostazioni di conformità del compilatore in Eclipse sono per Java 7? – robermann

+0

@robermann Nel mio caso, lo sono. Eclipse m2e configura le impostazioni di conformità del compilatore in base al POM. –

risposta

5

Dopo una profonda analisi da parte del team Eclipse la loro risposta a questo problema sta seguendo

Citato dopo Stephan Herrmann da Eclipse Bugzilla:

Questa linea non si applica per la seguente motivo:

Tipo inferenza inizia risolvendo questa espressione:

Optional.fromNullable(entry.getValue())

In questa espressione tutti gli elementi possono essere digitati come indicato sopra:

voce: voce di voce.getValue:
capture#2-of ? fromNullable(..) : (capture#2-of ?) -> Optional<capture#2-of ?>

In breve: T viene dedotta per essere "capture#2-of ?". L'inferenza ha successo

Solo dopo aver deciso, la risoluzione passa a per controllare la chiamata al metodo .or (..). Nessun motivo per inserire variabili di inferenza non dedotte con "Oggetto".

Con un ricevitore di tipo opzionale, abbiamo questi tre sovraccarichi di "o":

facoltativa o (opzionale)
capture#2-of ? or(Supplier<? extends capture#2-of ?> supplier)
capture#2-of ? or(capture#2-of ? defaultValue)

Nessuno di questi metodi è applicabile per un argomento di tipo Oggetto. CGE sceglie arbitrariamente il primo metodo per la segnalazione di errore:

"Il metodo o (opzionale) nel tipo opzionale non è applicabile per gli argomenti (Object)"

La differenza tra Corte di giustizia e javac è certamente coperto dalla insetto javac menzionato: https://bugs.openjdk.java.net/browse/JDK-8016207

Come indicato in tale errore, un futuro aggiornamento della JLS può eventualmente adottare parti del comportamento javac corrente. Fino a quando tale aggiornamento delle specifiche non è rilasciato , l'unico punto di riferimento affidabile per ecj è JLS. In questa specifica non vedo alcun motivo per modificare il comportamento di ecj in questo proposito.

BTW, la correzione canonica (senza getto necessario) è:

Optional.<Object>fromNullable(entry.getValue()).or(NO_VALUE);

Per ora che sarebbe la conclusione.

1

Non hai indicato una domanda, quindi presumo la domanda: "Chi ha ragione e come funziona il codice?"

Direi che Eclipse ha ragione.

Il risultato di fromNullable ha il parametro Tipo ?, vale a dire esiste un tipo T ma non lo sappiamo.

Il Optional restituito da or devono avere lo stesso parametro tipo del Optional viene chiamato, che significa anche che prende lo stesso tipo sconosciuto T come parametro. Ma Object potrebbe o potrebbe non essere compatibile con quel tipo, quindi è corretto fallire.

Al fine di risolvere il problema, penso che la seguente modifica dovrebbe funzionare:

Optional.fromNullable((Object)entry.getValue()).or(NO_VALUE); 

Il cast lega il parametro di tipo altrimenti sconosciuto a Object che è ovviamente compatibile con Object nella chiamata a or.

+0

Dato il contenuto della tua risposta, in particolare "* quindi è corretto fallire *", pensi davvero che Eclipse abbia ragione, non Maven? –

+0

Oops si. Aggiustato. Grazie per individuarlo. –

+0

Solleva la questione di ciò che viene definito come "giusto". Maven usa solo il 'javac' locale, che è forse giusto per impostazione predefinita. Eclipse ha il proprio compilatore incrementale, che probabilmente farei prima di mettere in dubbio l'implementazione di Oracle. Mi chiedo se le specifiche della lingua abbiano una visione su questo. –

1

Il compilatore di Eclipse è non standard javac. Usa lo ECJ Compiler Questo è sicuramente un bug nel compilatore di Eclipse, poiché maven usa il javac standard per compilare ecco perché funziona. (! Btw grande grazie)

+2

Le voci dicono che anche javac a volte contiene bug. –

+0

@JensSchauder sicuro, potrebbe.Ma prima interrogherei sul compilatore di Eclipse. – Eugene

+0

Sono d'accordo nel caso generale, ma non riesco a vedere come abbia senso compilarlo. –

Problemi correlati