当前位置: 首页 > 科技观察

凌驾:哎,这11条规矩我就不告诉你了

时间:2023-03-16 16:09:59 科技观察

天呐,久违了!关于Java的文章终于来了。快扶寡妇们起来,我又来了——叮(明眼人都能看出来,我是受了大秦之横行天下的影响)。回到主题。重写(Overriding)是Java中一个非常重要的概念。了解什么是重写对于每个Java程序员来说都是非常重要的。规则。01.什么是重写?重写带来了一个非常重要的能力,可以让子类重新实现从父类继承的方法。下图中,Animal是父类,Dog是子类。Dog重新实现了move()方法以区别于父类。毕竟,狗跑起来很有特色。重写后的方法和重写后的方法不仅方法名相同,参数也相同(也就是说方法签名相同),只是方法体不同。02.哪些方法可以重写?规则1:只能重写继承的方法。因为重写发生在子类重新实现从父类继承的方法时,所以很容易理解只能重写继承的方法。这意味着只能重写被public、protected或default修饰的方法,被private修饰的方法不能被重写。Animal类具有三个方法:move()、eat()和sleep():publicclassAnimal{publicvoidmove(){}protectedvoideat(){}voidsleep(){}}Dog类覆盖这三个方法:publicclassDogeextendsAnimal{publicvoidmove(){}protectedvoideat(){}voidsleep(){}}好的,完全没问题。但是如果父类中的方法是私有的,就不行了。publicclassAnimal{privatevoidmove(){}}此时,Dog类中的move()方法不再是override方法,因为父类的move()方法是私有的,对子类不可见。publicclassDogextendsAnimal{publicvoidmove(){}}03。哪些方法不能重写?规则2:final和static方法不能被重写。一个方法是final意味着它不能被子类继承,所以没有办法覆盖它。publicclassAnimal{finalvoidmove(){}}因为父类Animal中的move()是final的,子类试图重写这个方法时会出现编译错误!同样,如果一个方法是静态的,它就不能重写,因为静态方法对父类和子类的所有实例都可用。重写publicclassAnimal{finalvoidmove(){}}的目的是为了根据不同类型的对象表现出多态性,可以在不创建对象的情况下使用静态方法。没有对象,重写所需的“对象类型”就没有意义。04.重写方法要求规则三:被重写的方法必须有相同的参数列表。publicclassAnimal{voideat(Stringfood){}}Dog类中的eat()方法与父类方法eat()保持一致,只有一个参数——String类型的food。publicclassDogeextendsAnimal{publicvoideat(Stringfood){}}一旦子类不遵循这个规则,比如增加一个参数:publicclassDogeextendsAnimal{publicvoideat(Stringfood,intamount){}}这个就不再是重写的范围了,当然不是了重载的类别,因为重载考虑同一个类。规则4:重写的方法必须返回相同的类型。父类没有返回类型:publicclassAnimal{voideat(Stringfood){}}子类试图返回String:publicclassDogeextendsAnimal{publicStringeat(Stringfood){returnnull;}},所以出现编译错误(返回类型不兼容)。规则5:重写的方法不能使用具有更多限制级别的权限修饰符。可以这样理解:如果被重写的方法是default,那么被重写的方法可以是default、protected或public。如果被重写的方法是protected,那么被重写的方法只能是protected或者public。如果被重写的方法是public,那么被重写的方法只能是public。比如父类中的方法是protected:publicclassAnimal{protectedvoideat(){}}子类中的方法可以是public的:publicclassDogeextendsAnimal{publicvoideat(){}}如果子类中的方法被修改了更严格的权限字符,编译器报错。规则六:重写的方法不能抛出比父类更高级的异常。比如父类中的方法抛出IOException,那么子类中重写的方法不能抛出Exception,可以是IOException的子类也可以不抛出任何异常。此规则仅适用于已检查的异常。可检查(checked)的异常必须在源代码中被显式捕获和处理。Unchecked(未检查)异常就是所谓的运行时异常,比如NullPointerException、ArrayIndexOutOfBoundsException等,在编译器中不会强制要求。父类抛出IOException:publicclassAnimal{protectedvoideat()throwsIOException{}}子类抛出FileNotFoundException满足重写规则,因为FileNotFoundException是IOException的子类。publicclassDogeextendsAnimal{publicvoideat()throwsFileNotFoundException{}}如果子类抛出一个新的异常,而且是checkedexception:publicclassDogeextendsAnimal{publicvoideat()throwsFileNotFoundException,InterruptedException{}},那么编译器会提示错误:Error:(9,16)java:com.itwanger.overriding.Dog中的eat()不能重写com.itwanger.overriding.Animal中的eat()重写的方法不会抛出java.lang.InterruptedException但是如果子类抛出一个uncheckedexception,有是没有冲突的:publicclassDogeextendsAnimal{publicvoideat()throwsFileNotFoundException,IllegalArgumentException{}}如果子类抛出更高级别的异常:publicclassDogeextendsAnimal{publicvoideat()throwsException{}}编译器也会提示错误,因为Exception是IOException的父类.Error:(9,16)java:eat()incom.itwanger.overriding.Dogcannotoverrideeat()incom.itwanger.overriding.Animal重写的方法不抛出java.lang.Exception05,如何调用重写的方法?规则七:可以在子类中通过super关键字调用父类中重写的方法。子类继承父类的方法而不是重新实现它是很常见的。在这种情况下,可以通过以下形式调用父类的方法:super.overriddenMethodName();看一个例子。publicclassAnimal{protectedvoideat(){}}子类重写了eat()方法,然后在子类的eat()方法中,可以通过第一行super.eat()调用父类的方法方法体,然后再添加自己的代码。publicclassDogeextendsAnimal{publicvoideat(){super.eat();//狗吃}}06.重写和构造方法规则八:构造方法不可重写。因为构造方法很特殊,子类的构造方法不能和父类的构造方法重名(类名不同),所以构造方法和重写没有关系。07.重写和抽象方法规则九:如果一个类继承了一个抽象类,那么抽象类中的抽象方法必须在子类中被重写。先看这样一个接口类:publicinterfaceAnimal{voidmove();}接口中的方法默认是抽象方法,通过反编译可以看出:publicinterfaceAnimal{publicabstractvoidmove();}如果一个抽象类实现了Animal接口,则move()方法不必重写:publicabstractclassAbstractDogiimplementsAnimal{protectedabstractvoidbark();}但是如果一个类继承了抽象类AbstractDog,那么无论是Animal接口中的move()方法还是抽象类中的抽象方法bark()AbstractDogmustRewritten:publicclassBullDogextendsAbstractDog{publicvoidmove(){}protectedvoidbark(){}}08.重写和synchronized方法规则十:synchronized关键字对重写规则没有影响。synchronized关键字用于在多线程环境下获取和释放监听对象,所以对重写规则没有影响,也就是说一个synchronized方法可以重写一个异步方法。09.重写和strictfp方法规则十一:strictfp关键字对重写规则没有影响。如果想让浮点运算更准确,又不想因为硬件平台不同导致执行结果不一致,可以在方法中加上strictfp关键字。所以strictfp密钥与重写规则无关。本文转载自微信公众号“沉默王二”,可通过以下二维码关注。转载本文请联系沉默王二公众号。