1.方法重写的定义
重载(overload)是在同一个类中的具有多个相同方法名,参数列表不同(的方法(返回类型可以不同),构造方法、普通方法、抽象方法都可以重载;重写(override)是在子类继承父类的时候重写,可以用@Override检查是否是重写方法,方法重载是一个类的多态性的表现,而方法重写是子类与父类的一种多态性表现。重载是编译时的多态性,重写是运行时的多态性
重写满足以下规则:(外壳不变,核心重写)
- 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类(java5 及更早版本返回类型要一样,java7 及更高版本可以不同)
- 重写方法的参数列表相同
- 重写方法的函数名相同
- 被重写方法的访问修饰符不能是private,重写的方法可以范围可以扩大 public > protected > default > private,但是不能缩小
- 被重写方法不能有修饰符 final
- 声明为 static 的方法不能被重写,但是能够被再次声明
- 抛出的异常范围可以被缩小,但不能被扩大
- 构造方法不能被重写
2.方法的重写后调用(父类引用和子类引用接受子类new的对象)
class Person {
protected String name="Person name";
protected static String staticName="Person staticName";
public String getName() {
System.out.println("function call of Person");
return name;
}
public static String showName() {
System.out.println("static function call of Person");
return staticName;
}
}
class Man extends Person {
protected String name="Man name";
protected static String staticName="Man staticName";
public static String showName(){
System.out.println("static function call of Man");
return staticName;
}
@Override
public String getName() {
System.out.println("function call of Man");
return name;
}
}
2.1 static方法重写
public static void main(String[] args) {
Person person= new Man();
Man man = new Man();
//静态
System.out.println("person call:");
System.out.println(person.showName());
//编译器警告不要通过实例调用类的静态方法
System.out.println("man call:");
System.out.println(man.showName());
}
/*输出
person call:
static function call of Person
Person staticName
man call:
static function call of Man
Man staticName
*/
2.2 非static方法重写
public static void main(String[] args) {
Person person= new Man();
Man man = new Man();
//非静态
System.out.println("person call:");
System.out.println(person.getName());
System.out.println("man call:");
System.out.println(man.getName());
}
/*输出:
person call:
function call of Man
Man name
man call:
function call of Man
Man name
*/
2.3 总结
子类引用 和 父类引用 接受 new 出来的 子类对象 时:
- 重写静态方法的调用取决于引用类型。因为引用直接调用的是类的方法,所以静态方法重写由引用类型决定
- 重写非静态方法时取决于构造函数。因为引用类型指向地址实际上是由构造函数决定的。实际上,可以根据多态特性来理解,c++有指针所以没用 virtual 时指向各自引用类型的函数。由于java没有指针,所以跳过了这一步,直接实现多态,也就是父类指针也可以指向子类对象,根据实际的构造函数调用对应的子类对象的方法。
3.多态
- 多态是方法的多态,属性没有多态性
3.1 instance of 操作符
格式:[左值] instanceof [右值]
- 左值与右值之间需要有直系的继承关系(一条继承路线上)才可以使用,否则编译器直接报错
- 左值可以是父类的指针,返回结果取决于左值指向的具体类,即new出来的对象类型。
- 实际上比较是左值 new 实例类型是否是右值的实例。其中子类是父类的实例,返回true
// Object是Person的父类,Person是Man和 Woman 的父类
Man man=new man();
System.out.println(man instanceof Man);//true
System.out.println(man instanceof Person);//true
System.out.println(man instanceof Object);//true
System.out.println(man instanceof Woman);//编译器直接报错!
System.out.println(man instanceof String);//编译器直接报错!
Pertson person =new man();
System.out.println(person instanceof Man);//true
System.out.println(person instanceof Person);//true
System.out.println(person instanceof Object);//true
System.out.println(person instanceof Woman);//编译器直接报错!
System.out.println(person instanceof String);//编译器直接报错!
4.类型转换
-
强制类型转换一般用于父类引用调用子类中其独有的方法。
-
因为父类比子类更高级,低转高可以直接使用,所以父类引用可以直接接受子类的引用。
-
高转低需要直接强制类型转换。父类引用调用子类中其独有的方法需要先把高的父类强制转换成子类。