2015-03-30 8 views
6

Si consideri il seguente esempio autosufficiente:Eclipse non riesce dove javac e IDEA riescono

package bloopers; 

import java.lang.annotation.Annotation; 

public final class Blooper5 
{ 
    interface Converter<T,F> 
    { 
     T convert(F from); 
    } 

    interface Identifier<T> 
    { 
    } 

    static class ConvertingIdentifier<F,T> implements Identifier<F> 
    { 
     ConvertingIdentifier(Converter<T,F> converter) 
     { 
     } 
    } 

    static final class AnnotationIdentifier 
    { 
     Identifier<Annotation> I1 = new ConvertingIdentifier<>( 
      a -> a.annotationType()); 
     Identifier<Annotation> I2 = new ConvertingIdentifier<>( 
      Annotation::annotationType); //<-- ERROR 
     Identifier<Annotation> I3 = new ConvertingIdentifier<>( 
      (Converter<Class<? extends Annotation>,Annotation>) 
      Annotation::annotationType); 
    } 
} 

Il codice di cui sopra compila bene sotto la seguente:

  • javac dalla riga di comando.
  • IntelliJ IDEA configurato per utilizzare il compilatore javac.

ma non riesce a compilare con il seguente:

  • Eclipse
  • IntelliJ IDEA configurato per utilizzare il compilatore Eclipse.

Eclipse non riesce a compilare la linea tracciata con <-- ERROR, dando il seguente messaggio:

The constructor Blooper5.ConvertingIdentifier<Annotation,Class<capture#5-of ? extends Annotation>>(Blooper5.Converter<Class<? extends Annotation>,Annotation>) is undefined

Certo, questo codice spinge davvero le capacità di inferenza di tipo generico parametro del compilatore, ma ancora, mi vorrebbe sapere con precisione qual è la discrepanza, non importa quanto piccola.

certa esposizione dei miei metodi nel caso in cui qualcuno riesce a vedere qualcosa di sbagliato che non riesco a capire:

Il comando che ho usato per compilare con javac era "c:\Program Files\Java\jdk1.8.0_40\bin\javac" Blooper5.java.

Ho la versione 14.1 di IntelliJ IDEA. Sotto Project Structure/SDKs ho solo "1.8" che punta a C:\Program Files\Java\jdk1.8.0_40 e sotto Project Structure/Modules il modulo specifico è configurato per utilizzare "Project SDK (1.8)" che elenca come 1.8 (java version "1.8.0_40").

Per quanto riguarda Eclipse, sto usando Eclipse for RCP and RAP Developers - Version: Luna Release (4.4.0) - Build id: 20140612-0600. Sotto Preferences/Java/Installed JREs ho solo jdk1.8.0_40, ed è l'impostazione predefinita. Sotto Execution Environments viene anche controllato come "JRE compatibile" di "JavaSE-1.8". E nel mio Project/Properties/Java Build Path/Libraries la "Libreria di sistema JRE" è [jdk1.8.0_40].

fatti più degno di nota:

  • non si tratta solo di me; fallisce anche nell'installazione di eclissi di un collega (molto simile).

  • IntelliJ IDEA dice che l'espressione lambda a -> a.annotationType() può essere sostituito con un riferimento metodo, ma se richiesto di farlo, lo fa non convertirlo in Annotation::annotationType; invece, lo converte in (Converter<Class<? extends Annotation>, Annotation>) Annotation:: annotationType.

Quindi, la domanda:

Ciò che sta causando queste discrepanze tra Eclipse e gli altri, e cosa si può fare per eliminare queste discrepanze?

(Ovviamente, l'obiettivo è quello di eliminare lo scenario, purtroppo, troppo spesso si verificano in cui uno sviluppatore si impegna codice che non riesce a compilare l'IDE di un altro sviluppatore.)

EDIT: Quando ho originariamente postato questa domanda ho pensato che l'idea usando anche il compilatore Eclipse ha compilato bene, ma ho sbagliato. Si scopre che è possibile ottenere che IDEA non riesca a compilare il codice sopra selezionando il compilatore Eclipse. Tuttavia, la domanda è perché c'è una discrepanza tra eclipse e javac.

+0

Quale Eclipse stai usando? Funziona bene su Luna (versione 4.4.0) –

+0

@RohitJain wh00ps, scusa per l'omissione, ho aggiornato la domanda per includere quell'informazione. Quindi, sto anche usando Luna 4.4.0. O_O –

+0

Posso anche riprodurlo su Eclipse Luna. –

risposta

4

La risposta a "perché c'è una discrepanza" è semplice ma forse non molto soddisfacente: perché i compilatori hanno bug e sono inoltre aperti all'interpretazione di una specifica del linguaggio molto complessa. Determinare se si tratta di un bug in javac o Eclipse è un compito difficile; Ho visto che tali discrepanze finiscono per essere dichiarate in entrambi i modi, a volte come bug del compilatore Eclipse, a volte come bug javac. Quella determinazione, specialmente quando coinvolge i generici e le nuove caratteristiche linguistiche (come i lambda), può diventare piuttosto noiosa e arcana. Ad esempio, guarda questo che si è rivelato un errore javac ma ha scoperto un problema correlato nel compilatore di Eclipse: https://bugs.eclipse.org/bugs/show_bug.cgi?id=456459

La soluzione migliore è segnalarlo come un bug di Eclipse come ho fatto io e vedere se il compilatore di Eclipse il team può/lo rintraccerà.