重载(overloading)
重载 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。构造器就是最常见的重载。
举个例子
public class User { private String name; private int age; public User(String name, int age) { this.name = name; this.age = age; } public User(){} public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
在上述方法中有一个名称相同的方法User() 而他的参数不同。这样可以在调用这个方法的时候根据参数的顺序和类型来决定具体调用哪个方法。
由以上可以看出 重载就是在同一个类(子类)中,方法名称相同,参数列表不同(个数,类型,顺序)的方法。一个方法是否重载和返回类型,修饰符,抛出的异常是否一致没有关系。
补充:如果只有返回值不同方法名相同是否可以构成重载?
public static void main(String[] args){ String s=sayHello(); sayHello(); } static void sayHello(){ sout("hello"); } static String sayHello(){ sout("hello"); return s="hello"; }
上述代码一定是报错的,假设我们没报错让他运行,main方法根本无法确定你要调用的是哪个方法,因为java中是允许调用一个有返回值的方法时不接收返回值。当有同名同参的方法,会搞不清要调用哪个造成混乱。
重写(Override)
重写是对子类对父类的能够访问到的方法的具体方法体进行重新编写,方法返回值,方法名,形参都不能改变。即换壳不换皮。
举个例子:
class User{ public void eat(){ System.out.println("我要吃饭"); } } class Peolpe extends User{ public void eat(){ System.out.println("我不想吃饭"); } } public class Client{ public static void main(String args[]){ User a = new User(); User b = new People(); a.eat(); b.eat(); } }
上述代码执行结果为
我要吃饭
我不想吃饭
变量b明明指向的是User类型的对象 执行的却是People类型的对象内的方法。
因为在编译.class文件时,只是检查参数的引用类型并不会创建对象,而在运行时JVM会指定对象的类型并调用该对象方法。
所以在这里可以看出重载和重写很明显的一个区别,重载在编译时就可以确定 而重写在运行时才能确定。(ps.编译时同一个类里发现有同名不同参的方法就可以确定是重载,而重写是在不同的类里无法判断,直到运行的时候jvm调用对象的方法,发现父类和子类都有相同的方法啊,此时运行子类的方法,构成重写)
总结:相比于重载,
- 重写要求子类必须继承了某个方法,并且重写的方法和原方法参数列表一致,
- 返回类型和被重写方法的返回类型可以不相同,但必须是父类返回值的派生类(比如上文的方法,如果父类要求返回User类型,子类返回People也是可以的),
- 访问权限不能低于父类声明的权限(父类如果为Public 你就不能为protected)
- 声明为final的方法不能重写
- static方法不能被重写
- 构造方法不能重写(但能够用super()调用父类默认的无参构造)
对比:重载和重写都是java多态的一种体现形式(一个方法或者对象可以有多种形态存在)
重载是一个类的多态,重写是子类和父类的多态
权限:重载对权限没有要求,重写要求重写的方法权限不能低于继承的方法权限
返回类型:重载对返回类型没有要求 重写要求必须相同(或为派生类)
方法名:重载和重写要求方法名必须相同
参数:重载的参数一定不一致,重写的参数类型一定一致
确定时间:重载在编译时就确定,重写在对象调用具体方法时才确定