子类重写父类注意事项 java

A、重写规则之一:
    重写方法不能比被重写方法限制有更严格的访问级别。
(但是可以更广泛,比如父类方法是包访问权限,子类的重写方法是public访问权限。) 比如:Object类有个toString()方法,开始重写这个方法的时候我们总容易忘记public修饰符,编译器当然不会放过任何教训我们 的机会。出错的原因就是:没有加任何访问修饰符的方法具有包访问权限,包访问权限比public当然要严格了,所以编译器会报错的。

B、重写规则之二:
   参数列表必须与被重写方法的相同。
重写有个孪生的弟弟叫重载,也就是后面要出场的。如果子类方法的参数与父类对应的方法不同,那么就是你认错人了,那是重载,不是重写。     

C、重写规则之三:
   返回类型必须与被重写方法的返回类型相同。
父类方法A:void eat(){} 子类方法B:int eat(){} 两者虽然参数相同,可是返回类型不同,所以不是重写。
父类方法A:int eat(){} 子类方法B:long eat(){} 返回类型虽然兼容父类,但是不同就是不同,所以不是重写。

D、重写规则之四:

   重写方法不能抛出新的异常或者比被重写方法声明的检查异常更广的检查异常。但是可以抛出更少,更有限或者不抛出异常。

下面这段话是百度知道上一个人对于上面这句话的解释,我觉得蛮形象的,所以就拿出来share一下

子类抛出的异常类型不能比父类抛出的异常类型更宽泛!
对于这句话你还少了一个条件应该是子类重写父类方法不能抛出比父类更宽的异常类型的把。
其实理解这个很简单,比如说宪法规定骂人只承担民事责任,到了刑法里就不能说直接枪毙了,这就是一个约束能力的问题,
子类行为不能超出父类约束范畴。否者就容易乱套。就像父类的某方法公有的,子类就不能重写改成私有的了。这就是一个约束力的问题。 还有我查到说抛出runtime异常没有问题。运行时异常虽然可以不用捕获。但如果其本身已经超出了父类的范围呢?
这个还是拿宪法民事责任来说把,宪法说骂人教育一下就可以了,到了省里说道个歉就可以了,但是到了市里了,不光道歉还要写检讨。
这些都是可以的,因为他们本身就有处理这个事件的能力。子类方法他可以不管RuntimeException之类的异常,这是前提, 就算你父类方法声明的异常更小,我可以行使我抛出RuntimeException异常的权利,这个是我的本身就有的权利。
这就像是地方政策和国家政策相抵触的时候,老百姓可以直接往国家报告,可以不经过地方政府一样,因为老百姓有直接上报国家的权利。 子类有RuntimeException异常不报告的权利,就算你父类规定个更低的异常,我一样可以上报,只要你比RuntimeException低级就可以。
这就好比,卖国贼选择了卖国,他们的子女就不能爱国了一样!

import java.io.*;
public class Test {
  public static void main (String[] args) {
   Animal h = new Horse();
   try {
     h.eat();
   }
   catch (Exception e) {
   }
 }
}

class Animal {
  public void eat() throws Exception{
   System.out.println ("Animal is eating.");
   throw new Exception();
  }
}

class Horse extends Animal{
   public void eat() throws IOException{
    System.out.println ("Horse is eating.");
    throw new IOException();
  }
}

这个例子中,父类抛出了检查异常Exception,子类抛出的IOException是Exception的子类,也即是比被重写的方法抛出了更有限的异常,这是可以的。如果反过来,父类抛出IOException,子类抛出更为宽泛的Exception,那么不会通过编译的。
注意:这种限制只是针对检查异常,至于运行时异常RuntimeException及其子类不再这个限制之中。

E、重写规则之五:
   不能重写被标识为final的方法。

F、重写规则之六:
  如果一个方法不能被继承,则不能重写它。
比较典型的就是父类的private方法。下例会产生一个有趣的现象。
public class Test {
  public static void main (String[] args) {
   //Animal h = new Horse();
   Horse h = new Horse();
    h.eat();
   }
}

class Animal {
   private void eat(){
    System.out.println ("Animal is eating.");
    }
 }

class Horse extends Animal{
   public void eat(){
     System.out.println ("Horse is eating.");
   }
}
     这段代码是能通过编译的。表面上看来违反了第六条规则,但实际上那是一点巧合。Animal类的eat()方法不能被继承,因此Horse类中的 eat()方法是一个全新的方法,不是重写也不是重载,只是一个只属于Horse类的全新的方法!这点让很多人迷惑了,但是也不是那么难以理解。
main()方法如果是这样:
Animal h = new Horse();
//Horse h = new Horse();
h.eat();
编译器会报错,为什么呢?Horse类的eat()方法是public的啊!应该可以调用啊!请牢记,多态只看父类引用的方法,而不看子类对象的方法!


发布了36 篇原创文章 · 获赞 6 · 访问量 22万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章