重写
重载和重写是不一样的:
- 重载只是方法中参数列表(形参个数或顺序等)的不同,而重写是针对于有子父类关系的类中方法的(子类重写父类的方法)。
- 重写都是方法的重写,和属性没有任何关系
//重载 参数列表跟方法体都可以不同,但是方法名必须相同
public int add(int a,int b){return a+b;}
public int add(int a,int b,int c){return a+b+c;}
//重写 只有方法体不同,其余都必须相同(修饰符可以按照规则修改)
class Son extends Father{
public void test(){
System.out.println("调用子类中方法");
}}
class Father{
public void test(){
System.out.println("调用父类中方法");
}}
重写和static修饰的静态方法没有关系,重写只体现在非静态方法中。
有继承关系的两个类之间,以父类为声明,但是父类的引用可以指向子类的对象,相当于父亲找儿子借东西,在静态方法中对象调用的方法是所指向的声明类(父类)中的方法。
父类的引用指向了子类,即声明的是父类,但实际指向了子类的对象
Father f1=new Son();
//new Son(); 指的是父类所指向的引用类型
//Father 指的是对象的实际类型(声明)
例如:
public class Application{
public static void main(String[] args){
Son son = new son();
son.test();
//静态方法中,方法的调用只和左边即数据定义类型有关
Father father = new son();
//父类的引用指向了子类,但father对象还是父类定义的
//所以所用的仍然是父类中的方法
father.test();
}
}
class Son extends Father{
public static void test(){
System.out.println("调用子类中方法");
}
}
class Father{
public static void test(){
System.out.println("调用父类中方法");
}
}
非静态方法中子类重写了父类的方法,父类创建的对象但所指向的引用类型是子类的话调用该对象中被父类被重写的方法执行的还是子类的方法。
非静态类方法的重写(注意上下两代码之间的区别和输出结果):
public class Application{
public static void main(String[] args){
Son son = new son();
son.test();
//父类的方法被子类重写之后,创建的新的对象的是父类所声明的,引用类型指向子类
//但是该对象调用方法时调用的是子类中被重写的方法,这就与静态方法的操作有所不同
Father father = new son();
father.test();
}
}
class Son extends Father{
public void test(){
System.out.println("调用子类中方法");
}
}
class Father{
public void test(){
System.out.println("调用父类中方法");
}
}
重写的规则:
1、子类重写父类的方法其方法名必须与父类被重写的方法名相同
2、方法中的参数列表必须相同
3、方法的修饰符的范围可以扩大,但是不能缩小
public > protected > default > private
4、抛出的异常可以缩小但是不能扩大。
为什么要重写:因为有些父类的功能子类不一定需要,或者不一定满足,当方法很复杂的时候重新定义一个方法又太麻烦,这个时候就需要用到重写了。
多态:一个方法根据发送对象的不同可以呈现不同的行为方式
多态的意义:可以提高程序的可扩展性
多态是方法的多态,跟属性没有关系
多态的存在条件:
1、类之间有继承关系
2、方法被重写
3、父类的引用指向子类的对象
不能被重写的方法的一些修饰符:final,private,static
一个对象的实际类型是确定的,但是它所指向的引用类型是不确定的:父类的引用类型可以指向子类
子类可以调用自己的或者所继承的父类的方法
父类可以指向子类但是不能调用子类独有的方法
源码如下:
public class Application {
public static void main(String[] args) {
Son son = new Son(); //子类的引用类型指向子类
son.test(); //调用子类自己的方法
son.study("Bob");
son.teach("Alice");
Father father = new Father(); //父类的引用类型指向了父类本身
father.test(); //调用父类自己的方法,这个test()方法虽然被子类重写但是调用的是父类中的test()方法
father.teach("John");
Father father1 = new Son(); //父类的引用类型指向子类
father1.teach("Eric"); //调用父类独有的方法,不能调用子类独有的方法
father1.test(); //调用子类重写的test()方法,调用的是子类中的重写后的方法
//子类的引用类型不能指向父类
}
}
class Son extends Father{
//定义一了一个子类的属性,无法重写父类的name属性
public String name;
//子类的独有方法
public void study(String name){
System.out.println(name+"学生在学习");
}
//重写父类的test()方法
public void test(){
System.out.println("子类的方法被调用了");
}
}
class Father {
//定义了一个父类的属性
public String name;
//父类的独有方法
public void teach(String name){
System.out.println(name+"老师在教书");
}
public void test(){
System.out.println("父类的方法被调用了");
}
}