上次我们说到子类可以通过super关键字调用父类的构造的方法如果子类没有调用那就默认调用父类默认的构造方法,可是如果父类没有默认的构造方法怎么办?
父类代码:
public class Parent { public Parent(String name){ System.out.println("name="+name); } }
这时子类必须在构造方法中调用父类的构造方法,不然编译会报错,并且调用父类构造方法的代码必须写在第一行。
public class Child extends Parent{ public Child(String name) { super(name); } }
下面我需要向大家介绍几个名词。还记的上篇文章的Animal类和Dog类吗?其中Animal类是父类,Dog类是子类,在程序中调用时我们写的是: Dog dog = new Dog("红色"),这是一点问题都没有的。但是在java中我们还可以这样写: Animal animal = new Dog("红色")。此时,我们声明的类型是Animal而实际真正的类型是Dog,像这样把子类的对象赋值给父类的引用叫做向上转型。这时使用animal变量调用eat方法实际调用的子类对象的方法叫做多态,即一种类型的变量可以引用多种实际类型对象(取自:java编程的逻辑)。这时,对于变量animal,它就有两个类型:类型Animal叫做变量animal的静态类型;类型Dog叫做animal的动态类型,而animal.eat()实际调用的是动态类型的eat方法,称之为方法的动态绑定。
刚才我们解释了什么叫做多态,什么叫做动态绑定。那么有动态绑定就应该有静态绑定。静态绑定在程序的编译期就已经确定。比如类中的静态变量,父类中的静态变量和子类中的静态变量即使重名,使用父类的类名调用的就是父类的静态变量,使用子类的类名调用的就是子类的静态变量。这时,我们可能在想既然把子类对象赋值给父类引用叫做向上转型,那么如果把子类引用赋值给父类对象是否就是向下转型。在java语法中可以通过强制类型转化实现,但是并不安全。例如:
public static void main(String[] args) { Animal animal = new Dog("红色"); Dog dog = (Dog)animal; }
上面的代码没有问题,因为变量animal的动态类型就是Dog。可是如果是这样:
public static void main(String[] args) { Animal animal = new Animal(); Dog dog = (Dog)animal; }
变量animal的动态类型是Animal在java编译期不会报错但是在运行期就会抛出类型转化异常。所以这时我们需要使用关键字instance来判断变量animal是否是Dog类的实例。