【个人总结】谈谈Java继承后方法调用的常见误区

Example 1

在这里插入图片描述
这个例子中,Horse类继承了Animal,在实例化过程中,分别用Animal new了Animal,Horse new了Horse以及Animal new了Horse。经过测试可以发现,在方法调用上使用的分别是定义时类的方法,因为在传入到UseAnimal时是根据其定义时的类,例如Animal a = new Horse,即使实际上是Horse,但是编译时会传到第一个方法,其他的也是这样。
记住一点,重载是在编译阶段完成,重写于运行时完成。

Example 2

class Animal { 
	public void eat() {
		System.out.println("I'm an animal. I like eating everything!");
	}
}

class Horse extends Animal {
	public void eat(String food) {
		System.out.println("I'm a horse. I like eating "+ food);
	}
	public void eat() {
		System.out.println(“I‘m a horse. I like eating grass!"
	}
}

为了更好的区分,下面举几个例子:
Animal a = new Animal(); a.eat(); =>I’m an animal. I like eating everything!

Horse h = new Horse(); h.eat();=>I’m a horse. I like eating grass!

Animal ah = new Horse(); ah.eat();=>I’m a horse. I like eating grass!
这个例子这是多态性的体现,和Example 1有很好的对照,会调用实际类的方法。

Horse he = new Horse(); he.eat(“Apples!”);=>I’m a horse. I like eating Apples! The overloaded eat(String s) method in Horse is invoked.

Animal a2 = new Animal(); a2.eat(“Carrots”);=>Compiler error! Animal class doesn’t have an eat() method that takes a String

Animal ah2 = new Horse(); ah2.eat(“Carrots”);=>Compiler error!
这个例子也要特别注意,作为Animal类实例化,没有接受String的eat方法。

Example 3

在这里插入图片描述
第一个显然是不会编译通过的,接口无法实例化。
第二个会调用Dog类的方法,第三个会调用Cow类的方法。
注意第四个是无法调用成功的,因为Animal接口中不存在这个方法。

Example 4

    public static void main(String[] args) {
        A a = new A();
        System.out.println(a.getClass());

        A b = new B();
        System.out.println(b.getClass());
    }

再看这个例子,其中B是A的子类,结果如下:
class A
class B
可以发现,getClass能够返回其实际的类型。

Summary

搞清楚了上面几个例子就能避免很多错误和误区。
把握一个原则,重写方法后调用会执行子类的方法,除非在子类内部使用super.method(),无论将其作为什么定义(父类或子类)。
而如果调用了如上述Animal,即父类没有,子类的有的方法,无论是新的方法还是重载的方法都是不会成功的,因为编译时还是认为它是Animal。
在getClass时,能够返回其实际的类,但传参时会根据其定义的类(参考Example 1)。

发布了75 篇原创文章 · 获赞 28 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Swocky/article/details/93401093