2009-03-06 5 views
2

Dans le code ci-dessous, je voudrais que la deuxième méthode soit générique, aussi, mais depuis que je crée l'objet Calendar dans la méthode, à cause de type erasure, je ne vois pas comment. Une possibilité serait de passer dans l'objet Calendar, mais cela irait à l'encontre de l'objectif principal d'avoir cette méthode du tout (ne pas avoir à penser aux objets Calendar).Java: Les génériques ne fonctionneront pas pour ma méthode, que puis-je faire d'autre?

Comment puis-je faire fonctionner la deuxième méthode pour plusieurs sous-classes de Calendar, comme le fait la première méthode?

public static <U extends Calendar> CalendarMatch<U> tpFromCalendar(U dt) 
{ 
    // we want to do all comparisons on UTC calendars 
    dt.setTimeZone(TimeZone.getTimeZone(DEFAULT_TZ_ID)); 
    return new CalendarMatch<U>(dt); 
} 

public static CalendarMatch<GregorianCalendar> tpDailyGregorian(int h) 
{ 
    GregorianCalendar dt = new GregorianCalendar(TimeZone.getTimeZone(DEFAULT_TZ_ID)); 
    dt.clear(); 
    dt.set(Calendar.HOUR, h); 

    // this works because of type inference 
    return tpFromCalendar(dt); 
} 

Répondre

5

Il n'est absolument pas nécessaire d'utiliser la réflexion ici. Alors non!

public static <U extends Calendar> CalendarMatch<U> tpDailyGregorian(
    int h, CalendarFactory<U> factory 
) { 
    Calendar dt = factory.create(TimeZone.getTimeZone(DEFAULT_TZ_ID)); 
    dt.clear(); 
    dt.set(Calendar.HOUR, h); 

    // this works because of type inference 
    return tpFromCalendar(dt); 
} 

Où:

public interface CalendarFactory<U extends Calender { 
    U create(TimeZone timeZone); 
} 
+0

Ce qui est vrai - mais alors vous devez avoir une classe CalendarFactory par la sous-classe de calendrier. Evidemment ce n'est pas un gros problème pour Calendar mais c'est (évidemment) un problème pour d'autres classes génériques (comme EnumSet par exemple). –

+0

Malgré la syntaxe épouvantable de Java, ce n'est pas trop mal d'écrire une classe interne anonyme. –

+0

Je suppose que non :-) Le vôtre est une meilleure suggestion bien sûr –

3

La signature pourrait être:

public static <U extends Calendar> CalendarMatch<U> tpDailyGregorian(int h, Class<? extends U> clazz); 

Une façon serait d'utiliser la réflexion pour instancier votre calendrier (en passant dans le type Calendar):

Constructor<? extends U> c = clazz.getContructor(TimeZone.class); 
U dt = c.newInstance(TimeZone.getTimeZone(DEFAULT_TZ_ID)); 

Bien sûr, avec cette instance dt, vous pouvez uniquement appeler des méthodes sur Calendar et non GregorianCalendar

dt.clear(); 
dt.set(Calendar.HOUR, h); 

Date d = dt.getGregorianChange(); //CANNOT CALL THIS! 
Questions connexes