Можно ли выбрать, какой замещаемый метод использовать в Java? - PullRequest
1 голос
/ 10 июля 2020

У меня есть экземпляр java. sql .Date, и я хочу использовать метод java .util.Date.toInstant () вместо java. sql .Date.toInstant (), например, это возможно?

Ответы [ 2 ]

5 голосов
/ 10 июля 2020

java .time и JDB C 4.2

Я рекомендую вам придерживаться java .time, современного Java API даты и времени, которому принадлежит Instant, и забыть о нем. два класса Date, упомянутые в вопросе. Оба они плохо спроектированы и оба давно устарели. Начиная с JDB C 4.2, мы можем получать типы java .time из ResultSet.

Я предполагаю, что ваш запрос SQL возвращает SQL тип данных date.

    PreparedStatement stmt = yourDatabaseConnection
            .prepareStatement("select your_date_column from your_table;");
    ResultSet rs = stmt.executeQuery();
    while (rs.next()) {
        LocalDate date = rs.getObject("your_date_column", LocalDate.class);
        // do something with date
    }

Вы хотите преобразовать дату в Instant? Это преобразование не имеет смысла. SQL date обычно представляет собой календарную дату, определяемую годом, месяцем и днем ​​месяца, без часового пояса. Instant - это момент времени, совершенно другой зверь. Если вы можете выбрать время суток и часовой пояс для использования, преобразование возможно. Один из вариантов:

        Instant inst = date.atStartOfDay(ZoneId.systemDefault()).toInstant();

Если вы не можете избежать получения java. sql. Дата

Имея java.sql.Date, нам снова нужно время суток и время. зона, если мы хотим преобразовать в Instant. Есть причина, по которой java.sql.Date.toInstant() безоговорочно выбрасывает UnsupportedOperationException (что, я думаю, заставило вас задать вопрос). Я бы преобразовал Date в LocalDate, а затем продолжил бы, как раньше:

    java.sql.Date oldfashionedSqlDate = getFromSomewhere();
    Instant inst = oldfashionedSqlDate.toLocalDate()
            .atStartOfDay(ZoneId.systemDefault())
            .toInstant();

Более короткая, но более низкоуровневая и криптографическая c альтернатива:

    Instant inst = Instant.ofEpochMilli(oldfashionedSqlDate.getTime());

Эти два способа не всегда могут давать одинаковый результат, и это должно быть вашим первым советом при выборе. В случае, если Date, вопреки спецификации, содержит время дня, отличное от начала дня, последний метод даст вам это время, тогда как первый даст вам начало дня как код говорит. Кстати, последнее - это то, что делает java.util.Date.toInstant().

В общем, можно ли обойти реализацию метода в подклассе и напрямую вызвать метод суперкласса?

Можно ли выбрать какой переопределенный метод использовать в Java?

Нет, в этом языке это невозможно. Java не предлагает синтаксиса для такой уловки. Комментарий Хольгера под этим ответом, похоже, предполагает, что это возможно через отражение при некоторых обстоятельствах, например, когда вы можете открыть модуль java.base. См. Последнюю ссылку внизу для получения дополнительных сведений.

Ссылки

4 голосов
/ 10 июля 2020

Чтобы ответить на ваш вопрос, как задано:

Ваш код, использующий java.sql.Date, не может вызывать метод в java.util.Date, который java.sql.Date отменяет.

Это нарушит абстракцию данных, а язык Java не позволяет этого. Вы даже не можете сделать это рефлексивно.

(Как показывают другие ответы и комментарии, существуют альтернативные подходы, позволяющие избежать этой проблемы. Некоторые более практичны, чем другие 1 .)

1 - Идея создания настраиваемого подтипа java.sql.Date нецелесообразна. Вы не хотите изменять драйверы JDB C, чтобы попытаться решить эту проблему.

...