Как ковариантные типы параметров работают в Java

Учитывая, что у Date есть метод под названием «after (Date)», а у Timestamp есть метод, переопределяющий его под названием «after (Timestamp)», почему в следующем коде вызывается метод after в Date?

Вопрос о неожиданных результатах был задан здесь .

    java.sql.Timestamp one = new java.sql.Timestamp(1266873627200L);
    java.sql.Timestamp two = new java.sql.Timestamp(1266873627000L);

    java.util.Date oneDate = (java.util.Date) one;
    java.util.Date twoDate = (java.util.Date) two;


    System.out.println("one: " + oneDate.getTime());
    System.out.println("two: " + twoDate.getTime());

    if (oneDate.after(twoDate)) {
        System.out.println(oneDate.getTime() + " after " + twoDate.getTime());
    } else {
        System.out.println(oneDate.getTime() + " not after " + twoDate.getTime());
    }

Результаты

one: 1266873627200
two: 1266873627000
1266873627200 not after 1266873627000

person s_t_e_v_e    schedule 09.03.2010    source источник


Ответы (1)


Перегрузки рассматриваются во время компиляции; переопределения учитываются во время выполнения.

Отметка времени перегружает after, она не переопределяет существующий метод, поэтому ваш oneDate.after(twoDate) учитывает только методы в java.util.Date; более того, даже если вы используете one.after(twoDate), он все равно будет использовать только after(Date), потому что типом времени компиляции twoDate является Date, а не Timestamp.

Если вы вызовете one.after(two), то тот будет использовать Timestamp.after(Timestamp).

Date.after(Date) учитывает только миллисекунды, но Timestamp передает конструктору Date только целое число секунд, поэтому oneDate и twoDate имеют одинаковое значение миллисекунды в Date, даже если вы передали конструкторам разные значения.

Об этом стоит упомянуть в документации для Timestamp < / a> хотя:

Из-за различий между классом Timestamp и классом java.util.Date, упомянутым выше, рекомендуется, чтобы код не просматривал значения Timestamp в общем как экземпляр java.util.Date. Отношение наследования между Timestamp и java.util.Date на самом деле означает наследование реализации, а не наследование типов.

Честно говоря, мне кажется, что использование наследования является довольно плохим - но в Java их предостаточно :(

person Jon Skeet    schedule 09.03.2010
comment
Метод after в Date не сравнивает нано. - person s_t_e_v_e; 10.03.2010
comment
@s_t_e_v_e: А, я бы немного неправильно понял вывод. !x.after(y) - это не то же самое, что y.after(x) - это то, что предлагает ваш вывод. - person Jon Skeet; 10.03.2010