2010-04-13 10 views
9

np. Poniższy kod generuje wyjątek ClassCastException, gdy drugi obiekt zostanie dodany do zestawu TreeSet. Nie można zapisać obiektu TreeSet, aby parametr type mógł być tylko typem porównywalnym? , tj. TreeSet nie skompilowałoby się, ponieważ obiekt nie jest porównywalny. W ten sposób generics rzeczywiście wykonują swoją pracę - bycie bezpiecznym.Dlaczego JavaSet TreeSet nie określa, że ​​jego typ parametru musi być porównywalny?

import java.util.TreeSet; 
public class TreeSetTest { 
    public static void main(String [] args) { 
    TreeSet<Object> t = new TreeSet<Object>(); 
    t.add(new Object()); 
    t.add(new Object()); 
    } 
} 

Odpowiedz

4

Jeśli typ musiałby być porównywalny, nie można utworzyć zestawu drzewiastego o nieporównywalnym typie i komparatora (który można teraz taki, jaki jest teraz).

Jednym ze sposobów rozwiązania tego problemu przy zachowaniu bezpieczeństwa typów byłoby posiadanie dwóch klas: jednej z porównywalnym parametrem i jednej z nieporównywalnym parametrem typu i bez domyślnego konstruktora (tylko konstruktor, który pobiera komparator), ale przypuszczam, że deweloperzy javy nie chcieli wprowadzić dwóch klas, które zasadniczo zrobiłyby to samo (choć można go było łatwo zaimplementować jako wrapper wokół drugiego).

Innym (i prawdopodobnie czystszym sposobem) byłoby rozszerzenie systemu typów, tak aby niektóre konstruktory istniały tylko wtedy, gdy są używane z pewnymi parametrami typu (tj. Domyślny konstruktor istnieje tylko wtedy, gdy parametr typu jest porównywalny), ale przypuszczam, że sprawili, że ogólny system jest zbyt złożony dla java.

+0

Dzięki za wyczerpującą odpowiedź. Lol, myślę, że ogólny system jest już wystarczająco skomplikowany! – Tarski

13

TreeSet nie wymaga jego parametr typu być Comparable, ponieważ może to potrwać zewnętrznego Comparator do porównywania innych niż Comparable wartości.

+0

Ah dzięki. Przypuszczam, że nie ma sposobu, aby określić ograniczenie dla konstruktora no-args, tak aby mogła wziąć tylko Comparables? Czy byłoby lepiej zaprojektować dwie klasy - jedną, która przyjmuje parametr typu Porównywalne i taką, która przyjmuje dowolny typ parametru, ale jej konstruktorzy muszą wziąć Komparatory? – Tarski

+4

@Tarski: 'TreeSet' został dodany w wersji 1.2. Generics zostały dodane w 1.5. –

1

To dlatego, że wartość , a nie koniecznie trzeba wdrożyć Comparable. Obiekt można jawnie przekazać obiektowi Comparator, w którym to przypadku typ elementu nie musi być Comparable.

0

Można również utworzyć TreeSet z Comparator jako parametrem konstruktora. Wtedy twoje przedmioty nie muszą być porównywalne.

Powiązane problemy