我已经看到子类的constructer方法用于具有超类类型的变量。例如:
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
formatter
是DateFormat
类型对象还是SimpleDateFormat
类型?由于类SimpleDateFormat
继承自DateFormat
,因此它的方法可能比其超类更多。实例formatter
调用这些函数只能存在于SimpleDateFormat
但不存在DateFormat
吗?在这种情况下,DateFormat
和SimpleDateFormat
是否可以互换?如:
SimpleDateFormat formatter = new DateFormat ("yyyy-MM-dd");
答案 0 :(得分:3)
formatter
的运行时类型由用于实例化它的构造函数确定,其编译时类型是您在声明中使用的类型。除非使用强制转换来解析方法调用,否则不能在格式化程序上调用其实际运行时类型而不是其声明类型的方法。
顺便说一句,你可以通过简单的实验回答你自己的问题:
public class SuperClass {
public void test() {
System.out.println("Test");
}
public static class SubClass extends SuperClass {
public void testSub() {
System.out.println("Test sub");
}
@Override
public void test() {
System.out.println("Override test");
}
}
public static void main(String[] args) {
SuperClass sc = new SuperClass();
sc.test(); // prints Test
sc = new SubClass();
sc.test(); // prints Override test
sc.testSub(); // does not compile
((SubClass) sc).testSub(); // prints Test sub
}
}
答案 1 :(得分:1)
Java实例的类型由用于创建它的构造函数确定,不能更改。
可以在实例上调用的方法取决于用于引用它的变量的类型。因此,您可以在同一实例上调用不同的方法集,具体取决于您用于引用它的变量的类型。
用于引用实例的变量类型可能是:
作为变量的类层次结构中的较高者,使用它的代码越通用(因此可重用)。作为设计规则,您应该使用Interfaces作为变量(和特殊参数)类型。
建议你阅读:http://en.wikipedia.org/wiki/Liskov_substitution_principle
答案 2 :(得分:0)
formatter
属于DateFormat
和SimpleDateFormat
两种类型。一旦调用SimpleDateFormat
的构造函数,它也会调用DateFormat
的构造函数 - 但它只是一个Object。
要从SimpleDateFormat
访问方法,您可以投射它:
SimpleDateFormat sdf = (SimpleDateFormat) formatter;
只有formatter
类型为SimpleDateFormat
或其任何子类时,此方法才有效。以下行将产生编译错误:
SimpleDateFormat sdf = (SimpleDateFormat) DateFormat.getDateTimeInstance();
顺便说一句,我只是从一开始就将formatter
声明为SimpleDateFormat
。将它声明为DateFormat
而不是施放它没有任何好处 - 这会浪费你的CPU。