Ho il seguente titolare del trattamento generica nel mio progetto (semplificato):Java 8 - la conversione di un numero intero di un problema di lunga compilation
public abstract static class Value<E> {
E value;
public void setValue(E value) {
this.value = value;
}
public E getValue() {
return this.value;
}
public String toString() {
return "[" + value + "]";
}
}
Insieme ad un InputCollection
che contiene un elenco di Objects
:
public static class InputCollection {
private ArrayList<Object> values;
public InputCollection() {
this.values = new ArrayList<>();
}
public void addValue(Value<?> value) {
System.out.println("addding " + value + " to collection");
this.values.add(value);
}
public <D> D getValue(Value<D> value, D defaultValue) {
int index = this.values.indexOf(value);
if (index == -1)
return defaultValue;
Object val = this.values.get(index);
if (val == null) {
return defaultValue;
}
return ((Value<D>)val).getValue();
}
}
L'idea è di essere in grado di definire un insieme di variabili final
che implementa questa abstract
Value<E>
in uno 'stato' cosiddetto, in questo modo:
public static final class Input<E> extends Value<E> {
public static final Input<String> STRING_ONE = new Input<String>();
public static final Input<Integer> INTEGER_ONE = new Input<Integer>();
}
Quindi, aggiungere queste variabili a un'istanza di InputCollection
, che a sua volta è condivisa da molti "stati" o "processi". Il valore di un Input<E>
può quindi essere modificato da uno stato diverso e quindi essere recuperato quando necessario dallo stato originale. Una sorta di modello di memoria condivisa.
Questo concetto è stato lavorando bene per anni (sì, questo è l'eredità), ma recentemente abbiamo cominciato a muoversi verso Java 8, e questo ha creato errori di compilazione, anche se l'implementazione ha lavorato su Java 7.
Add il seguente main
per gli esempi di codice di cui sopra:
public static void main (String [] args) {
InputCollection collection = new InputCollection();
//Add input to collection
collection.addValue(Input.STRING_ONE);
collection.addValue(Input.INTEGER_ONE);
//At some later stage the values are set
Input.INTEGER_ONE.setValue(1);
Input.STRING_ONE.setValue("one");
//Original values are then accessed later
long longValue = collection.getValue(Input.INTEGER_ONE, -1);
if (longValue == -1) {
System.out.println("Error: input not set");
} else {
System.out.println("Input is: " + longValue);
}
}
Se il livello di conformità del compilatore in Eclipse è impostato su 1,7, non c'è problemi di compilazione, e l'uscita sarà correttamente essere:
addding [null] to collection
addding [null] to collection
Input is: 1
ma se è impostato su errore di compilazione 1.8 Type mismatch: cannot convert from Integer to long
sulla linea
long longValue = collection.getValue(Input.INTEGER_ONE, -1);
Ma se accedo il valore di fare questo:
long longVal = Input.INTEGER_ONE.getValue();
non ci sono problemi di compilazione, il che è fonte di confusione.
Può essere risolto con un cast, ma questo è utilizzato in tutto il progetto e richiederebbe un bel po 'di test obbligatori per cambiare ogni occorrenza.
Cosa è cambiato in Java 8 che richiede il cast? La compilazione è diventata più severa in qualche modo? E perché il compilatore non si lamenta se il valore è l'accesso diretto e non attraverso la raccolta?
ho letto How do I convert from int to Long in Java? e Converting Integer to Long, ma non abbiamo davvero ottenere risposte soddisfacenti alla mia domanda.
Puoi provare a compilarlo con 'javac'? Ho anche avuto questo problema e credo che sia un bug di eclissi. Se ho aggiunto il cast nel mio codice, ha emesso un avviso "Cast non necessario" ... :) –
Non riesco a replicare sul mio computer. Funziona perfettamente bene nella mia con Java8. – Jatin
Questo è in effetti un bug nel compilatore interno di Eclipse. Nota: Eclipse non usa il comando 'javac' da un JDK installato, ma usa un compilatore interno. Questo compilatore riporta l'errore. La compilazione con gli strumenti JDK funziona bene. – Seelenvirtuose