2013-02-22 19 views
10

Nadal uczę się o generykach i mam pytanie. Załóżmy, że masz tę ogólną klasę:Jaka jest różnica między tymi instrukcjami w klasie ogólnej?

public class Test<T> { 

    public static void main (String[] args) { 
     Test t1 = new Test(); 
     Test<String> t2 = new Test<String>(); 
     Test t3 = new Test<String>(); 
    } 
} 

Wszystkie instrukcje są kompilowane, ale nie wiem, co je wyróżnia. Czy ktoś może dać mi krótkie wyjaśnienie tych trzech zdań.

+0

Prawie prawda. Pozostałe ostrzeżenia o dwóch reklamach, ale nie rzeczywisty błąd kompilacji. –

Odpowiedz

9
Test t1 = new Test(); 

Tutaj używasz Raw typ. tj. nie przekazuje się Type argument dla twojego s.

Kompilator powinien dać ostrzeżenie tutaj

test jest typu raw. Odniesienia do rodzajowego typu badania powinny być parametryzowane

Test<String> t2 = new Test<String>(); 

tutaj używasz rodzajowych. przekazywanie String jako type argument do Twojego generic class.

Test t3 = new Test<String>(); 

kompilator powinien również daje ostrzeżenie o zbyt:

  • testowy jest rodzajem surowe. Odniesienia do rodzajowego typu badania powinny być parametryzowane

samo jak pierwszym przypadku, ale używasz parametryczne typu podczas wywoływania konstruktora.

Istnieje również inna klasa, która działa poprawnie w wersjach + java 7.

Test<String> t4 = new Test<>(); 

Brak ostrzeżenia o kompilator jeśli używasz + java 7 ze względu na Inference

typu, w tym przypadku ze względu na wprowadzenie type inference typu rodzajowego jest wywnioskować, co nie trzeba, aby zapewnić ogólny type podczas wywoływania konstruktora.

+1

Powinniśmy również dodać, że oryginalne pytanie pominęło dwie kombinacje: 'Test t4 = new Test()', który nie będzie się kompilował, ponieważ próbuje przypisać referencję typu surowego do typu generycznego; i 'Test t5 = nowy test <>()', który kompiluje się przy użyciu nowego "operatora diamentu" w Javie 7. – yshavit

+1

+1, a od java 7 można również napisać Test t4 = new Test <>(); co jest równoznaczne z deklaracją t2 ... – pgras

+1

@yshavit i pgras właśnie dodali to chłopaki :) – PermGenError

2

Wszystkie one faktycznie tworzą identycznych obiektów. Jedyna różnica polega na tym, w jaki sposób są one traktowane syntaktycznie w pozostałej części kodu.

i t3 będą traktowane w dokładnie taki sam sposób, ponieważ są tego samego typu - będą traktowane jako obiekt z klasą Test, nic więcej.

t2 będzie traktowany bardziej rygorystycznie pod względem sprawdzania typu. Jeśli pojawi się jakaś okazja, aby kompilator mógł użyć swojej ogólnej jakości <String>, to ta jakość będzie również wymagana do dopasowania.

3

Generics zapewnia kontrolę typu kompilacji.

Pomaga dodać przykłady tego, co można/nie można zrobić z elementów (Zmieniłem Test do ArrayList dla ułatwienia przykładów):

ArrayList t1 = new ArrayList(); 
    ArrayList<String> t2 = new ArrayList(); 
    ArrayList t3 = new ArrayList<String>(); 

    // First list can have ANYTHING added to it 
    // Compiler won't check because no generics 
    t1.add(new Integer("7")); 
    t1.add("Hello"); 

    // Second list can only have Strings added to it 
    // Compiler will check and throw compile error for anything else 
    t2.add(new Integer("7")); // doesn't compile 
    t2.add("Hello"); 

    // Third list is interesting... 
    // Again, can have ANYTHING added to it 
    // This is because generics (in Java...) are swapped out at COMPILE time 
    // rather than RUNTIME. The compiler can see that the actual type is just 
    // plain ArrayList 
    // If you like, it's similar to doing: 
    // Object o = (String) new Object(); 
    // The net-effect is everything reduced back to Object 
    t3.add(new Integer("7")); // fine 
    t3.add("Hello"); 
Powiązane problemy