2017-02-09 2 views
10
public static <T> T foo(T x, T x2) { 
    return (T) (x + " " + x2); 
} 

public static void main(String args[]) { 
    System.out.println(foo(33, "232")); 
} 

Ich weiß, T wird von dem Typ sein, der im Parameter übergeben wird. Aber hier gibt es zwei Arten. Welcher von ihnen ist T?Warum kompiliert dieser generische Code in Java?

und warum zwingt mich der Compiler nicht, die Parameter des gleichen Typs zu haben, wenn ich foo rufe?

+12

Es ist zulässig, weil 'T'' Objekt' sein kann, so dass Sie die Methode zwei beliebige Objekte übergeben können. ('32' kann in diesem Fall ein' Integer' sein und nicht ein 'int'). – khelwood

+1

Und die obere Grenze von' T' ist 'Objekt', also ist im' kompilierten Code' die Besetzung '(T)' ' (Object) ', was gilt, weil' String' ein 'Objekt' ist. –

+1

Auch um die Kommentare hinzuzufügen, das ist der Grund, warum Sie nie ungebundene Typen verwenden möchten (die Generika werden weggelassen), da prinzipiell jede Kombination von Klassen gültig ist. Wenn Sie dies tun, befinden Sie sich möglicherweise in einer Situation, in der 'ClassCastExceptions' das übliche Ergebnis der Arbeit mit den Rohtypen – SomeJavaGuy

Antwort

16

Es ist zulässig, da Integer und String einen gemeinsamen Basistyp haben. T kann Object sein, also wird foo(T, T) zwei beliebige Objekte akzeptieren. 32 kann zu einer Integer autoboxed werden, die eine Art Object ist. "232" ist eine String, die eine Art Object ist.

(Wie Kommentaren darauf hingewiesen, für Integer und String gibt es eine engere gemeinsame Basis-Typ, Serializable;., Aber das Prinzip ist das gleiche je nachdem, was Basis der Compiler T Typ löst)

+0

Können Sie beschreiben, was in dieser Zeile passiert: 'return (T) (x +" "+ x2)'? Entspricht es return (Object) (x.toString() + "" + x2.toString()) '?Wenn ja, was passiert im Casting, wenn es eine Zeichenkette zum Objekt wirft, dann wie diese Zeichenkette im Druck abgerufen wird? – TheLogicGuy

+1

@TheLogicGuy Wenn Sie versuchen, ein Objekt zu einem String hinzuzufügen, wird es mit 'toString()' konvertiert. Wenn Sie versuchen, ein Objekt zu drucken, wird es mit 'toString()' in einen String konvertiert. (Wenn Ihr Objekt eine Zeichenkette ist, gibt 'toString()' nur 'this' zurück.) – khelwood

5
public static <T> T foo(T x, T x2) { 
    return (T) (x + " " + x2); 
} 

es ist zu beachten, dass, während diese kompiliert, kann es zur Laufzeit fehlschlagen:

int f = foo(1, 2); 

werden Ideone demo scheitern, weil die Methode ein String zurückgibt, nicht ein Integer.

Es kompiliert, obwohl, weil Typ Löschung bedeutet, dass T die obere Grenze neu geschrieben wird, nämlich Object. Also:

public static Object foo(Object x, Object x2) { 
    return (Object) (x + " " + x2); 
} 

Das ist in Ordnung, weil das Ergebnis ein String ist, das ist ein Subtyp von Object.

Ich denke, das ist nur ein Fall, wo die Generika-Modell es warten, um Sie zu fangen. Deshalb würde ich es vermeiden, Generika und explizites Casting zu mischen.

+1

int f = foo (1, 2); wird nicht kompiliert .. – Brovoker

+0

@Brovoker warum nicht? –

+0

Da keine Instanz des Typs Variable existiert, so dass T konform ist mit Int – Brovoker

Verwandte Themen