java类的继承中方法的覆盖与重载

java类的继承中方法的覆盖与重载

我们都知道,java中类是可以继承的,而在继承中方法是可以覆盖或者重载的。以前一直在纠结什么时候是覆盖,而什么时候又是重写,直到前几天,终于把一些搞通。以下是本人的一点小结。有总结的不好的,欢迎各位大神指出

原始代码:

class Animal{
    public void sayHello(){
        System.out.println("hello~");
    }
}

class Cat extends Animal{
    public void sayHello(){
        System.out.println("good~");
    }
}
public class Client{
    public static void main(String []args){
        Cat c = new Cat();
        c.sayHello();
        Animal a = new Cat();
        c.sayHello();
    }
}

代码中我们可以看到,Cat继承Animal,且其中都只有一个sayHello方法。参数个数,返回值类型与方法名都与父类Animal相同,符合java程序书继承中类方法的覆盖规则,毫无疑问输出都是good~.即此时的确是方法的覆盖而非重载。接下来,我们再新增一个类,代码如下:

class Animal{
    public void sayHello(){
        System.out.println("Animal say hello~");
    }
}

class Cat extends Animal{
    public void sayHello(){
        System.out.println("Cat say hello~");
    }
}
class Dog extends Animal{
    public void sayHello(){
        System.out.println("dog say Hello~");
    }
}
public class Client{
    public static void main(String []args){
        Animal a = new Dog();
        a.sayHello();
        Animal a1 = new Cat();
        a1.sayHello();
    }
}

输出结果为:

dog say Hello~
Cat say hello~

代码中可看出,我们增加了一个类,Dog继承Animal,且Dog中也有相同的一个方法sayHello(),只是输出内容不相同。在控制台中分别输出了 Dog say Hello~与 Cat say hello。这是因为我们在main方法中声明的对象都为Animal,但是new的类不同,所以调用的方法也不相同。
由此总结出一条结论:当子类继承同一个父类时,我们new的是哪一个类,则调用的就是哪一个类的方法。
看到这里我相信不禁有人会问,如果出现多重继承呢,即Cat类又有一个类去继承它,那么这个方法是否还是可以使用呢?
答案是肯定的,我们不妨在上面的代码中增加以下代码:

class Kitty extends Cat{
    public void sayHello(){
        System.out.println("Kitty say Hello~");
    }
}

即我们又新建一个类Kitty,这个类继承了Cat,而Cat又继承了Animal。它们的关系为:
Kitty->Cat->Animal
Animal类为祖先类,Cat变成了,Kitty为子类。我们依旧声明父类,然后用new运算符创建不同的类,创建对象的代码为:
Animal a1 = new Cat();
a1.sayHello();
Animal a2 = new Kitty();
a2.sayHello();
然后输出结果为:

Cat say hello~
Kitty say Hello~

依旧遵循 当子类继承同一个父类时,我们new的是哪一个类,则调用的就是哪一个类的方法。
由此看出,这条结论是正确的。

查阅java程序设计基础,上面关于继承时类方法的覆盖是这样定义的:
覆盖是指在子类中,定义名称,参数个数与返回值类型均与父类完全相同的方法,用来重写父类中同名方法的操作。
看到这里,我相信大多数的同学都大概明白了,我们只要明确的记住。覆盖时,只有子类的方法名和父类相同,返回值类型和父类完全相同,参数类型与个数和父类相同时才会发生覆盖,否则一律为重载。
但是,可能也有的同学会这么问:要是子类没有父类的方法,new的是子类的对象,那么再用这个对象去调用父类的那个方法,会出项什么情况呢?是编译不通过,还是会调用父类的方法呢?
不急,我们再看看以下代码:

class Animal{
    public void sayHello(){
        System.out.println("Animal say hello~");
    }
}

class Cat extends Animal{
}
public class Client{
    public static void main(String []args){
        Animal a1 = new Cat();
        a1.sayHello();
    }
}

代码中我们可以看到。Animal类中空空无一,但是我们却能编译通过,且运行时结果为:

Animal say hello~

出现这种情况的原因是因为Cat类继承了Animal类,自然的也就把Animal类的方法也给继承过来了。随意运行的时候首先会去子类看看有没有那个方法,如果有,则优先调用子类的方法,若没有,那么再去父类找这个方法。若把Animal方法写成private的话就会出现编译出错的情况。因为继承中我们知道,私有的方法是不能被继承的。

说到私有方法不能被继承,我们不禁会有这样一个疑问。若父类的方法为私有,但是子类方法为public类型的。然后我们再用声明父类指向子类的方式去创建对象,然后用这个对象去调用这个方法。那么又会出现什么情况呢?
这个我们修改后的代码:

class Animal{
    private void sayHello(){
        System.out.println("Animal say hello~");
    }
}
class Cat extends Animal{
    public void sayHello(){
        System.out.println("Animal say hello~");
    }
}
public class Client{
    public static void main(String []args){
        Animal a1 = new Cat();
        a1.sayHello();
    }
}

然后我们编译:

Client.java:14: 错误: sayHello()可以在Animal中访问private
                a1.sayHello();
                  ^
1 个错误

我们会发现,出错了。很多朋友相信都纳闷了。怎么会出错了呢,上面不是说new的是哪个对象,调用的就是哪一个对象的方法吗?难道是刚才的结论有错?
事实不是这样的。刚才的那个结论依旧是正确的。上面我们刚刚说过,继承中子类只能继承父类中protected以上的方法(若子类与父类在同一个包中,也能继承缺省的),而这里我们写的是private,这是不能被继承的,既然不能被继承,那么又何来覆盖一说?所以它就会用子类的对象去访问父类的私有方法,而因为这个方法是私有的,即使new 的是父类的对象,都不能调用,子类更是不可能了。由此我们也得出一个经验,当我们写私有方法时,一定要特别小心。因为这个方法用正常的方式根本不可访问。而实际开发中,我们也几乎只在特定的方法下才写私有方法。

然后我们再这样修改代码。保持参数类型和个数,方法的返回值完全相同。但是访问修饰符不同,又会出现什么情况呢?
我们来看代码:

class Animal{
    public void sayHello(){
        System.out.println("Animal say hello~");
    }
}
class Cat extends Animal{
    protected void sayHello(){
        System.out.println("Animal say hello~");
    }
}
public class Client{
    public static void main(String []args){
        Animal a1 = new Cat();
        a1.sayHello();
    }
}

这个时候,我们依旧是用父类指向子类的方式去创建对象。但是父类的访问修饰符为public,而子类为protected;即子类的访问修饰符比父类低。然后我们再来看看编译结果:

Client.java:7: 错误: Cat中的sayHello()无法覆盖Animal中的sayHello()
        protected void sayHello(){
                       ^
  正在尝试分配更低的访问权限; 以前为public
1 个错误

糟糕,又出错了。什么原因呢?最后问了一下老师,然后才知道,原来java中关于方法的覆盖还有一大两小这么个说法
这是我自己总结的一大两小原则:
*大:
1.子类的访问修饰符 大于等于 父类的访问修饰符
两小:
1.子类的返回类型 小于等于 父类的返回类型
2.抛出异常时,只能 小于等于 父类的异常*
以上结论本人已经全部实验过。都是正确的。因为篇幅太长,在这里就不一一写出来了。看到这里的各位也可以自己验证验证,有不懂得欢迎提问。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 是的,Java覆盖重载都体现了多态性。 覆盖(Override)是在子重写父已有的方法,用子的实现覆盖同名方法。在运行时,当调用该方法时,根据实际对象的型来确定调用的方法。这就是动态多态性的体现。 重载(Overload)是在一个定义多个同名方法,但它们的参数型或个数不同,这样在调用这些方法时,编译器根据传递的参数型和个数选择最合适的方法进行调用。这就是编译时多态性的体现。 Java覆盖重载都是多态性的表现,但是它们的实现方式不同,覆盖是运行时多态性,而重载是编译时多态性。 ### 回答2: Java覆盖重载都是多态性在面向对象编程的体现。 覆盖(Overriding)是指在子重新定义父已有的方法。子通过覆盖可以改变父方法的实现方式,但仍然保持方法名称和参数列表相同。当使用父的引用指向子对象时,调用该方法根据对象的实际型来确定要执行的方法,体现了动态绑定。这种灵活的行为正是多态性的体现。 重载(Overloading)是指在一个定义多个具有相同名称但参数列表不同的方法重载方法可以具有不同的参数型、参数个数或参数顺序,但返回型可以相同也可以不同。当调用重载方法时,编译器根据实际传入的参数来决定要调用的具体方法,体现了静态绑定。重载能够提供更多的方法调用选择,增加了程序的灵活性和可读性。 通过覆盖重载Java实现了多态性。多态性是面向对象编程的重要特征之一,它允许使用父的引用来指向不同子的对象,从而实现对不同对象的统一操作。多态性使得程序更加灵活、可扩展,并且减少了代码的重复性。 总之,Java覆盖重载通过提供不同的方法调用方式,体现了多态性的概念和特征。使用多态性的编程方式可以提高程序的灵活性、可读性和可维护性。 ### 回答3: Java覆盖重载是实现多态性的两种重要手段。Java的一种,可以在继承一个的同时,根据自身的需求对父的某些方法进行覆盖覆盖即子对父同名方法的重新实现,子可以根据自己的需要重新定义该方法的行为。这样,在使用父引用指向子对象时,通过调用被覆盖方法根据实际的对象型调用相应的实现,实现了多态性的特点。 另外一种实现多态性的方式是重载Java允许在一个定义多个同名方法,只要它们的参数型或参数个数不同。当程序调用这个方法时,编译器根据传入的参数型和个数来匹配对应的方法进行调用。重载一个重要特点是方法名相同但参数不同,这样可以增加代码的复用性,不同的方法根据输入参数的型或个数来选择执行适当的操作。 通过覆盖重载Java实现了多态性,使得不同型的对象可以根据实际情况调用适当的方法。这种灵活性和扩展性可以提高代码的复用性和可维护性,同时也简化了程序的设计和开发过程。多态性是面向对象编程的重要特征之一,Java覆盖重载就是多态性在语法层面的具体实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值