tags:

views:

193

answers:

2

In the code below, I would like the second method to be generic, too, but since I create the Calendar object inside the method, because of type erasure, I don't see how. One possibility would be to pass in the Calendar object, but that would defeat the main purpose for having this method at all (not having to think about the Calendar objects).

How can I make the second method work for multiple subclasses of Calendar, like the first method does?

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);
}
+3  A: 

The signature could be:

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

One way would be to use reflection to instantiate your calendar (passing in the Calendar type):

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

Of course, with this dt instance, you can only call methods on Calendar and not GregorianCalendar

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

Date d = dt.getGregorianChange(); //CANNOT CALL THIS!
oxbow_lakes
+5  A: 

There is absolutely no need to use reflection here. So don't!

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);
}

Where:

public interface CalendarFactory<U extends Calender {
     U create(TimeZone timeZone);
}
Tom Hawtin - tackline
That's true - but then you have to have one CalendarFactory class per calendar subclass. Obviously this is not a big issue for Calendar but is (obviously) an issue for other generic classes (like EnumSet for example).
oxbow_lakes
Despite Java's all round appalling syntax, it's not too bad to write an anonymous inner class.
Tom Hawtin - tackline
I suppose not :-) Yours is a better suggestion of course
oxbow_lakes