2013-06-05 12 views
8

ho avuto una prova di colloquio e ha visto il seguente codice:Valore generico Java. <SomeValue>

EDIT:

public class TestValue { 
    private Value<SomeValue> defaultValue; 

    @Test 
    public void Empty_Value_Has_No_Value() { 
     Assert.assertFalse(Value.<SomeValue> createEmptyValue() 
      .hasValue()); 
    } 

    @Test 
    public void Default_Value_IsEmpty() { 
     Assert.assertEquals(Value.<SomeValue> createEmptyValue(), 
      defaultValue); 
    } 

    @Test 
    public void Non_Empty_Value_Has_Value() { 
     Assert.assertTrue(new Value<SomeValue>(true, new SomeValue()) 
      .hasValue()); 
    } 
} 

Non avevo mai visto Java generico come

Value.<SomeValue> 

Il test è quello di implementare classe di valore con il dato codice di test unitario sopra.

ho cercato di capire la firma del metodo valore al di sotto (necessità di implementazione):

public interface Value<T> { 

    public boolean hasValue(); 
    public Value<T> createEmptyValue(); 
} 

Uno sa, si prega di aiuto?

Grazie

EDIT: dovrebbe essere così in base alle risposte qui sotto @marlon

public class Value<T> { 

    public boolean hasValue(){} 
    public static <M> Value<M> createEmptyValue(){}; //need <M> 
} 

La sintassi chiave per sapere:

Value.<SomeValue> //ClassName.<Type>method 

è modo per richiamare il metodo statico di una classe con argomento parametrizzato.

MODIFICA: in base a @ snipes83, sintassi per richiamare il metodo non statico di una classe con argomento parametrizzato.

SomeObject.<Type>method 
+3

potrebbe essere un errore di battitura? 'Il valore .createEmptyValue()' ha più senso. – Snps

+0

Era una codifica della lavagna? Forse è solo un riferimento a un tipo che può essere qualsiasi cosa per definizione, nel senso che fornisce un valore di quel tipo, ma il tipo non ha molta importanza? Questo è quello che assumerei in questo caso. – clement

+0

Sì; tipo di curioso me stesso. –

risposta

6

Value.<SomeValue> è il modo in cui i generici vengono rappresentati per i metodi.

Utilizzo di Google Guava di Optional come esempio:

Optional<String> email = Optional.<String>of(strEmail); 

Vedi Generic Types - Invoking generic methods

Dal momento che le interfacce non può dichiarare metodi statici (vergogna su di voi java), basta dichiarare il vostro metodo statico e dimenticare l'interfaccia, in questo modo:

class Value<T> { 

    public static <T> Value<T> createEmptyValue(){ 
     return null; 
    } 
} 
+0

Vuoi dire createEmptyValue() in quanto sopra dovrebbe essere statico? come valore statico pubblico createEmptyValue(); // errore di compilazione: impossibile creare un riferimento statico al tipo non statico T – Eric

+1

@Eric: quasi, ma si dovrebbe parametrizzare il metodo statico su '', come 'valore statico pubblico Valore createEmptyValue() {... } '. Come indicato dal compilatore, non è possibile fare riferimento a un parametro non statico T sulla classe da un metodo statico. –

+0

@ Eric, Ryan Stewart Aggiornamento della mia risposta per riflettere i vostri commenti. –

2

1) questo è metho modo generico ds sono invocati. Fare riferimento >>http://docs.oracle.com/javase/tutorial/java/generics/methods.html

2)<SomeValue> in Value.<SomeValue> è opzionale. Il compilatore può inferire il tipo. Questo è chiamato TypeInference. Suggerire >>http://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html

Risposta Aggiornato:

3)Value.<SomeValue> createEmptyValue() è giusto e Value.<SomeValue>createEmptyValue() è giusto anche. Entrambi i modi sono legali. L'ho appena testato. Non ho notato prima.

+0

Ho provato che funziona con lo spazio. Quindi entrambi in 3) dovrebbero andare bene? – Eric

+0

Come è attualmente scritto, l'unica differenza tra i due esempi dati in numero (3) è lo spazio bianco; potresti approfondire la presunta differenza? – wchargin

+0

Awww, appena testato. Funziona. Dannazione, non l'avevo notato prima. –

3

un'occhiata alla classe Test con il metodo getEmptyList seguito:

public class Test { 
    public <T> List<T> getEmptyList() { 
     return new ArrayList<T>(); 
    } 
} 

restituisce un vuoto List contenenti oggetti di tipo T.

Se si utilizza Test come questo

Test t = new Test(); 
List<Integer> list = t.getEmptyList(); 

Poi il meccanismo di inferenza di tipo è in grado di dedurre il parametro di tipo in base al tipo variabile.

Tuttavia, se è necessario utilizzare il valore restituito getEmptyList all'interno di un'espressione chiamata di metodo come nel seguente esempio in cui il metodo printList aspetta un singolo argomento di tipo List<Integer>, allora il tipo non può essere rilevato dai qualsiasi tipo di variabile.

public void printList(List<Integer> list) { 
    for (int i : list) { 
     System.out.print(i); 
    } 
} 

printList(t.getEmptyList()); // This will FAIL. 

In questo caso è necessario specificare il tipo utilizzando il seguente:

printList(t.<Integer>getEmptyList()); 
1

Anche se Value è di per sé, ovviamente digitato (in base al tipo variabile di istanza di Value<SomeValue>), il metodo statico createEmptyValue() è anche digitato.

Un'assunzione ragionevole, se le convenzioni di denominazione sono state rispettate, è che SomeValue estende (o implementa) Value.

Anche se non ci esiste una risposta corretta, una possibilità probabile per la firma di Value è:

public class Value<T extend Value> { 
    public static <V extends Value> V createEmptyValue() { 
     // some impl 
    } 
}