Java重写时应当遵守的11条规则
CSDN 的⼩伙伴们,⼤家好,我是沉默王⼆。
重写(Overriding)算是 Java 中⼀个⾮常重要的概念,理解重写到底是什么对每个 Java 程序员来说都⾄关重要,这篇⽂章就来给⼤家说说重写过程中应当遵守的 12 条规则。
01、什么是重写?
重写带来了⼀种⾮常重要的能⼒,可以让⼦类重新实现从超类那继承过来的⽅法。在下⾯这幅图中,Animal 是⽗类,Dog 是⼦类,Dog 重新实现了move()⽅法⽤来和⽗类进⾏区分,毕竟狗狗跑起来还是⽐较有特⾊的。
重写的⽅法和被重写的⽅法,不仅⽅法名相同,参数也相同,只不过,⽅法体有所不同。
02、哪些⽅法可以被重写?
规则⼀:只能重写继承过来的⽅法。
因为重写是在⼦类重新实现从⽗类继承过来的⽅法时发⽣的,所以只能重写继承过来的⽅法,这很好理解。这就意味着,只能重写那些被 public、protected 或者 default 修饰的⽅法,private 修饰的⽅法⽆法被重写。
Animal 类有move()、eat()和sleep()三个⽅法:
public class Animal {
public void move() { }
protected void eat() { }
void sleep(){ }
}
Dog 类来重写这三个⽅法:
public class Dog extends Animal {
public void move() { }
protected void eat() { }
void sleep(){ }
}
OK,完全没有问题。但如果⽗类中的⽅法是 private 的,就⾏不通了。
public class Animal {
private void move() { }
}
此时,Dog 类中的move()⽅法就不再是⼀个重写⽅法了,因为⽗类的move()⽅法是 private 的,对⼦类并不可见。
public class Dog extends Animal {
public void move() { }
}
03、哪些⽅法不能被重写?
规则⼆:final、static 的⽅法不能被重写。
⼀个⽅法是 final 的就意味着它⽆法被⼦类继承到,所以就没办法重写。
public class Animal {
final void move() { }
}
java重写和重载的区别由于⽗类 Animal 中的move()是 final 的,所以⼦类在尝试重写该⽅法的时候就出现编译错误了!
同样的,如果⼀个⽅法是 static 的,也不允许重写,因为静态⽅法可⽤于⽗类以及⼦类的所有实例。
public class Animal {
final void move() { }
}
重写的⽬的在于根据对象的类型不同⽽表现出多态,⽽静态⽅法不需要创建对象就可以使⽤。没有了对象,重写所需要的“对象的类型”也就没有存在的意义了。
04、重写⽅法的要求
规则三:重写的⽅法必须有相同的参数列表。
public class Animal {
void eat(String food) { }
}
Dog 类中的eat()⽅法保持了⽗类⽅法eat()的同⼀个调调,都有⼀个参数——String 类型的 food。
public class Dog extends Animal {
public void eat(String food) { }
}
⼀旦⼦类没有按照这个规则来,⽐如说增加了⼀个参数:
public class Dog extends Animal {
public void eat(String food, int amount) { }
}
这就不再是重写的范畴了,当然也不是重载的范畴,因为重载考虑的是同⼀个类。
规则四:重写的⽅法必须返回相同的类型。
⽗类没有返回类型:
public class Animal {
void eat(String food) { }
}
⼦类尝试返回 String:
public class Dog extends Animal {
public String eat(String food) {
return null;
}
}
于是就编译出错了(返回类型不兼容)。
规则五:重写的⽅法不能使⽤限制等级更严格的权限修饰符。
可以这样来理解:
如果被重写的⽅法是 default,那么重写的⽅法可以是 default、protected 或者 public。
如果被重写的⽅法是 protected,那么重写的⽅法只能是 protected 或者 public。
如果被重写的⽅法是 public,那么重写的⽅法就只能是 public。
举个例⼦,⽗类中的⽅法是 protected:
public class Animal {
protected void eat() { }
}
⼦类中的⽅法可以是 public:
public class Dog extends Animal {
public void eat() { }
}
如果⼦类中的⽅法⽤了更严格的权限修饰符,编译器就报错了。
规则六:重写后的⽅法不能抛出⽐⽗类中更⾼级别的异常。
举例来说,如果⽗类中的⽅法抛出的是 IOException,那么⼦类中重写的⽅法不能抛出 Exception,可以是 IOException 的⼦类或者不抛出任何异常。这条规则只适⽤于可检查的异常。
可检查(checked)异常必须在源代码中显式地进⾏捕获处理,不检查(unchecked)异常就是所谓的运⾏时异常,⽐如说 NullPointerException、ArrayIndexOutOfBoundsException 之类的,不会在编译器强制要求。
⽗类抛出 IOException:
public class Animal {
protected void eat() throws IOException { }
}
⼦类抛出 FileNotFoundException 是可以满⾜重写的规则的,因为 FileNotFoundException 是 IOException 的⼦类。
public class Dog extends Animal {
public void eat() throws FileNotFoundException { }
}
如果⼦类抛出了⼀个新的异常,并且是⼀个 checked 异常:
public class Dog extends Animal {
public void eat() throws FileNotFoundException, InterruptedException { }
}
那编译器就会提⽰错误:
Error:(9, 16) java: com.itwanger.overriding.Dog中的eat()⽆法覆盖com.itwanger.overriding.Animal中的eat()
被覆盖的⽅法未抛出java.lang.InterruptedException
但如果⼦类抛出的是⼀个 unchecked 异常,那就没有冲突:
public class Dog extends Animal {
public void eat() throws FileNotFoundException, IllegalArgumentException { }
}
如果⼦类抛出的是⼀个更⾼级别的异常:
public class Dog extends Animal {
public void eat() throws Exception { }
}
编译器同样会提⽰错误,因为 Exception 是 IOException 的⽗类。
Error:(9, 16) java: com.itwanger.overriding.Dog中的eat()⽆法覆盖com.itwanger.overriding.Animal中的eat()
被覆盖的⽅法未抛出java.lang.Exception
05、如何调⽤被重写的⽅法?
规则七:可以在⼦类中通过 super 关键字来调⽤⽗类中被重写的⽅法。
⼦类继承⽗类的⽅法⽽不是重新实现是很常见的⼀种做法,在这种情况下,可以按照下⾯的形式调⽤⽗类的⽅法:
super.overriddenMethodName();
来看例⼦。
public class Animal {
protected void eat() { }
}
⼦类重写了eat()⽅法,然后在⼦类的eat()⽅法中,可以在⽅法体的第⼀⾏通过super.eat()调⽤⽗类的⽅法,然后再增加属于⾃⼰的代码。
public class Dog extends Animal {
public void eat() {
super.eat();
// Dog-eat
}
}
06、重写和构造⽅法
规则⼋:构造⽅法不能被重写。
因为构造⽅法很特殊,⽽且⼦类的构造⽅法不能和⽗类的构造⽅法同名(类名不同),所以构造⽅法和重写之间没有任何关系。
07、重写和抽象⽅法
规则九:如果⼀个类继承了抽象类,抽象类中的抽象⽅法必须在⼦类中被重写。
先来看这样⼀个接⼝类:
public interface Animal {
void move();
}
接⼝中的⽅法默认都是抽象⽅法,通过反编译是可以看得到的:
public interface Animal
{
public abstract void move();
}
如果⼀个抽象类实现了 Animal 接⼝,move()⽅法不是必须被重写的:
public abstract class AbstractDog implements Animal {
protected abstract void bark();
}
但如果⼀个类继承了抽象类 AbstractDog,那么 Animal 接⼝中的move()⽅法和抽象类 AbstractDog 中的抽象⽅法bark()都必须被重写:
public class BullDog extends AbstractDog {
public void move() {}
protected void bark() {}
}
08、重写和 synchronized ⽅法
规则⼗:synchronized 关键字对重写规则没有任何影响。
synchronized 关键字⽤于在多线程环境中获取和释放监听对象,因此它对重写规则没有任何影响,这就意味着 synchronized ⽅法可以去重写⼀个⾮同步⽅法。09、重写和 strictfp ⽅法
规则⼗⼀:strictfp 关键字对重写规则没有任何影响。
如果你想让浮点运算更加精确,⽽且不会因为硬件平台的不同导致执⾏的结果不⼀致的话,可以在⽅法上添加 strictfp 关键字。因此 strictfp 关键和重写规则⽆关。
到此这篇关于Java 重写时应当遵守的 11 条规则的⽂章就介绍到这了,更多相关Java 重写规则内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论