2013-07-31 18 views
6

Dlaczego tak się stało? Jedna linia kodu działa dobrze, a druga nie. Czy automatyczne odlewanie odbywa się tylko w określonych warunkach? Próbowałem przypisać gt.echoV() do obiektu i działa dobrze; ale kiedy przypiszesz go do String, ten sam błąd znowu się pojawi.Java rodzajowe typu metoda odlewania

public class GeneMethodTest { 

    public static void main(String... args) { 
     GeneMethodTest gt = new GeneMethodTest(); 
     gt.<String>echoV(); //this line works well 
     gt.<String>echoV().getClass();//this line leads to a type cast exception               
    } 

    public <T> T echoV() { 
     T t=(T)(new Object());                  
     return t; 
    } 
} 
+1

Ta odpowiedź może pomóc http://stackoverflow.com/a/3437930/1316346 –

+0

'(T) (nowy obiekt())' jest * niezaznaczoną obsadą * - pamiętaj, aby przeczytać o tym, co to jest i implikacje wraz z * typem wymazania *. –

+0

Tak, wiem to. @PaulBellora Właściwie (T) (new Object()) nic nie zrobi w czasie wykonywania z powodu usunięcia typu. Problem polega na tym, że dzwonię do gt. .echoV() automatyczne odlewanie klas nie działa, gdy zaczyna działać, gdy wzywam gt. echo.getClass() –

Odpowiedz

4

gt.<String>echoV().getClass(); produkuje równowartość następującej sekwencji operacji:

// Inside echoV 
Object t = new Object(); // Note that this is NOT a String! 
Object returnValue = t; 
// In main 
String stackTemp = (String) returnValue; // This is the operation that fails 
stackTemp.getClass(); 

Co można dostać „za darmo” z rodzajowych jest to, że (String) obsady. Nic więcej.

+0

Zgadza się. Wygląda na to, że kompilator wykombinuje, kiedy wstawić kod, zamiast wstawiać go za każdym razem ~ –

+0

@charles_ma - Tak, zabrać GetClassowi i figurkom kompilatora, że ​​nie ma potrzeby obsady. –

2

Działa to idealny, nic specjalnego, normalne korzystanie z leków generycznych

gt.<String>echoV(); //this line works well 

Tutaj mamy coś mniej oczywistego. Ponieważ są zdefiniowane w czasie wykonywania metoda rodzajowa robi JVM nie wiedzieć, jaki rodzaj klasy metoda rodzajowa powróci na compiletime, stąd classTypeException

gt.<String>echoV().getClass();//this line leads to a type cast exception 

należy przydzielonej do zmiennej po pierwsze, ponieważ JVM zna typ zmiennej w compiletime

String s = gt.<String>echoV(); 
s.getClass(); 
+2

Właściwie jeśli wykonujesz 'System.out.println (gt. echoV())' masz 'java.lang.ClassCastException'. –

+0

sam problem, System.out.println oczekuje ciąg jako parametr. Jeśli tak nie jest, wywoła to toString() obiektu, ale w kompilatorze jvm nie wie z jakiego obiektu –

+0

Myślę, że może dlatego, że w pierwszym wierszu nazwałem funkcję, ale nie użyłem referencje, więc kompilator nie zadał sobie trudu dodania kodu odlewania klasy; ale w drugim wierszu, próbowałem użyć wynikowego odwołania z wywołania, więc kompilator musiał wstawić tam kod klasy castingowej I taką samą sytuację, gdy wywołujesz System.out.println (gt. echoV()) @ System.exit –

1

zmienić tę linię:

gt.<String>echoV().getClass(); 

do:

(gt.echoV()).getClass(); 

i będzie to skompilować
(będzie to powrót: Klasa java.lang.Object)

Korzeń ClassCastException jest to, że metoda zwraca t (rodzajowy typu T który jest obiektem) i spróbować spuścić go na ciąg. Możesz również zmienić kod, aby wrócić:

return (T)"some-string"; 

w celu usunięcia błędu.

Generic są wykorzystywane przez kompilator, by sprawdzić, jaki rodzaj obiektu się spodziewać, więc może złapać błędy dewelopera poczynione w czasie kompilacji (błędy w porównaniu z run-time). Tak więc IMHO ten sposób użycia generyków pokonuje cel.

+0

downvoter - czy chcesz napisać komentarz? czy napisałem coś niedokładnego? – alfasin

+1

Myślę, że pytanie dotyczy użycia Generics, a nie samej metody'getClass() '. –

+1

@ System.exit Myślę, że moja odpowiedź również to obejmuje. – alfasin

Powiązane problemy