假设我有以下课程:
public class MyClass {
/* Note: Timestamp extends date */
public doSomething(java.sql.Timestamp timestamp){
System.out.println("Timestamp");
...
}
public doSomething(java.util.Date date){
System.out.println("Date");
...
}
}
假设我现在运用我的代码:
MyClass myClass = new MyClass();
Date realDate = new Date();
Timestamp timestamp = new Timestamp(0);
Date casted = new Timestamp(0);
myClass.doSomething(realDate); // prints Date
myClass.doSomething(timestamp); // prints Timestamp
myClass.doSomething(casted); // prints Date!!!!! What?!
我遇到的问题是,由于casted
实际上不是日期,因此当我使用它时它不起作用。
除此之外:一般来说,不起作用的子类不应该成为问题,但是时间戳的javadoc说:
由于Timestamp类和上面提到的java.util.Date类之间存在差异,因此建议代码不要将Timestamp值一般视为java.util.Date的实例。 Timestamp和java.util.Date之间的继承关系实际上表示实现继承,而不是类型继承。
我知道我可以这样做:
public doSomething(java.util.Date date){
if(date instanceof type){
System.out.println("Timestamp");
...
}
System.out.println("Date");
...
}
但这似乎很讨厌。
有没有办法让子类的方法重载工作而不使用巨型switch语句?
编辑:简而言之,似乎Timestamp
打破了Liskov substitution principle - 正如@Mick Mnemonic所指出的那样。
答案 0 :(得分:1)
是的。不是你的错误。这是java.util.Date
,java.sql.Date
和Timestamp
的设计怪癖。 (不要对它们太过刻薄。java.util.Date
现在已经二十岁了;当他们设计API时,他们仍然在弄清楚这些东西。)如果你直接使用这些类型,没有什么好办法。
一种方法是避免使用这些类,除非您需要,在与需要它们的API的边界处,并在其他地方使用更好设计的日期时间类型集。在您的数据访问层中,必要时使用Timestamp
的特殊情况instanceof
等。并将所有内容转换为内部代码的Joda-Time(适用于Java 7)或java.time
/ JSR-310(适用于Java 8)类型。 (如果在Java 7中实际需要纳秒精度,则需要使用自己的Timestamp对象来使用Joda-Time类型。不难;只需确保使用组合而不是像java.util
这样的实现继承伙计们!:))你可能会更开心。