1

以下示例中的实用程序方法仅用于说明目的。

在下面的示例中,instance method调用被分派到引用类型而不是运行时对象。

import java.sql.Timestamp;
import java.util.Date;
public class DynamicMethodDispatchEx {

    public static void main(String[] args) {
        Timestamp now = new Timestamp(System.currentTimeMillis());
        Timestamp beforeNow = new Timestamp(now.getTime() - 1);

        System.out.println("Finding newest in " + now + " and " + beforeNow);
        System.out.println("Attempt 1: " + staticFindNewer(beforeNow, now));
        System.out.println("Attempt 2: " + staticFindNewer(now, beforeNow));

    }

    public static Date staticFindNewer(Date one, Date two) {
        if (one.after(two)) {
            return one;
        } else {
            return two;
        }
    }

}

下面是我得到的输出

Finding newest in 2016-08-23 17:56:36.375 and 2016-08-23 17:56:36.374
Attempt 1: 2016-08-23 17:56:36.375
Attempt 2: 2016-08-23 17:56:36.374 // <---

经过一番调查,我发现尝试 1 和 2 中的差异java.util.Date.after(Date)被调用,staticFindNewer()并且是由于使用 Date 的方法导致的精度损失。

但是,我对动态调度感到困惑。我希望Timestamp#after(Timestamp)被调用,但Date#after(Date)被调用了。我认为实例方法调度总是基于运行时对象。我是否错过了一些愚蠢的事情(很可能)?

4

1 回答 1

1

我希望Timestamp#after(Timestamp)被调用,但Date#after(Date)被调用了。我认为实例方法调度总是基于运行时对象。

动态调度只发生在被调用的对象上,而不是参数上。

所以调用会转到Timestamp#after(Date)(因为参数的编译时类型是Date,而被调用者的运行时类型是Timestamp)。

不幸的是,Timestamp它没有覆盖这个方法,所以它默认返回Date#after(Date)(在这里不太好用)。

因此,您必须确保Timestamp#after(Timestamp)直接调用,或者改用该Date#compareTo(Date)方法,该方法已正确实现(并在 中覆盖Timestamp)。

于 2016-08-24T01:13:52.537 回答