2013-06-05 11 views
8

Ich hatte ein Interview Test und sah den folgenden Code:Java Generics Wert. <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()); 
    } 
} 

Ich hatte wie nie gesehen Java Generika

Value.<SomeValue> 

Der Test ist Wert Klasse mit der zur Umsetzung gegebener Unit Test Code oben.

Ich versuchte, den Wert Methode Unterschrift, um herauszufinden (Implementierung benötigen):

public interface Value<T> { 

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

Jeder weiß, bitte helfen?

Danke

EDIT: Sollte so sein nach Antworten unter @marlon

public class Value<T> { 

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

Der Schlüssel Syntax wissen:

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

ist Art und Weise statische Methode einer aufzurufen Klasse mit parametrisiertem Argument.

EDIT: nach @ snipes83, Syntax, um nicht-statische Methode einer Klasse mit parametrisierten Argument aufrufen.

SomeObject.<Type>method 
+3

Es ist ein Tippfehler sein könnte? 'Wert .createEmptyValue()' macht mehr Sinn. – Snps

+0

War das eine Whiteboard-Codierung? Vielleicht ist es nur ein Verweis auf einen Typ, der per Definition alles sein kann, nur bedeutet, dass sie einen Wert dieses Typs bereitstellen, aber der Typ ist nicht wirklich wichtig? Das würde ich in diesem Fall annehmen. – clement

+0

Ja; irgendwie neugierig. –

Antwort

6

Value.<SomeValue> es ist die Art und Weise Generika für Methoden dargestellt werden.

Mit Google Guava des Optional als Beispiel:

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

Siehe Generic Types - Invoking generic methods

Da Schnittstellen nicht statische Methoden (Schande über Sie java) erklären können, nur erklären, um Ihre Methode als statische und vergessen Sie die Schnittstelle, dies wie:

class Value<T> { 

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

Meinst du, createEmptyValue() in der oben genannten sollte statisch sein? wie public static Wert createEmptyValue(); // compile error: Kann keinen statischen Verweis auf den nicht-statischen Typ machen T – Eric

+1

@Eric: Fast, aber Sie würden die statische Methode auf '', wie 'public static Wert createEmptyValue() {... } '. Wie der Compiler darauf hinweist, können Sie nicht von einer statischen Methode auf einen nicht statischen Parameter T der Klasse verweisen. –

+0

@ Eric, Ryan Stewart Meine Antwort wurde aktualisiert, um Ihre Kommentare zu reflektieren. –

2

1) Dies ist, wie generische metho ds werden aufgerufen. Siehe >>http://docs.oracle.com/javase/tutorial/java/generics/methods.html

2)<SomeValue> in Value.<SomeValue> ist optional. Der Compiler kann den Typ ableiten. Dies wird TypeInference genannt. Siehe >>http://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html

Antwort Aktualisiert:

3)Value.<SomeValue> createEmptyValue() richtig und Value.<SomeValue>createEmptyValue() ist auch richtig. Beide Wege sind legal. Habe es gerade getestet. Hab vorher nicht bemerkt.

+0

Ich habe versucht, es funktioniert mit dem Raum. Also beide in 3) sollte in Ordnung sein? – Eric

+0

Wie es derzeit geschrieben wird, ist der einzige Unterschied zwischen den zwei Beispielen, die in Nummer (3) angegeben sind, der Leerraum; Könnten Sie den vermeintlichen Unterschied näher erläutern? – wchargin

+0

Awww, habe es gerade getestet. Es funktioniert. Verdammt, habe ich vorher nicht bemerkt. –

3

Blick auf die Klasse Test mit der Methode getEmptyList unter:

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

Es gibt eine leere List enthält Objekte vom Typ T.

Wenn Sie Test verwenden wie dieses

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

Dann wird der Typinferenz Mechanismus in der Lage, den Typ-Parameter auf dem Variablentyp basiert abzuleiten.

Allerdings, wenn Sie den Rückgabewert von getEmptyList innerhalb eines Methodenaufrufes Ausdruck wie im folgende Beispiel verwenden müssen, in dem das Verfahren printList ein einziges Argument vom Typ erwartet List<Integer>, dann kann der Typ nicht von jedem Variablentyp infered werden.

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

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

In diesem Fall können Sie den Typ mit der folgenden angeben müssen:

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

Obwohl Value selbst offensichtlich getippt (basierend auf der Instanz Variablentyp von Value<SomeValue>), die statische createEmptyValue() Methode auch ist getippt.

Eine vernünftige Annahme, wenn die Namenskonventionen eingehalten wurden, ist, dass SomeValue erweitert (oder implementiert) Value.

Obwohl es uns nicht eine richtige Antwort, eine wahrscheinliche Möglichkeit zur Unterzeichnung der Value ist:

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