重写
-
前提:需要有继承关系,子类重写父类的方法!
-
重写中,子类的方法和父类必须要一致,但方法体不同。
-
重写和重载:重写指子类重写父类的方法;
重载指同一个类中,参数列表不同的同名方法。
一个指向子类对象的父类引用变量来调用父子同名的静态方法时,只会调用父类的静态方法。这是因为 静 态 方 法 只 能 被 继 承 , 不 能 被 重 写 \color{red}{静态方法只能被继承,不能被重写} 静态方法只能被继承,不能被重写,如果子类有和父类相同的静态方法,那么父类的静态方法将会被隐藏,对于子类不可见,也就是说,子类和父类中相同的静态方法是没有关系的方法,他们的行为不具有多态性。但是父类的静态方法可以通过父类.方法名调用。
重写的特点:
-
子类和父类方法的方法名必须相同。
-
子类和父类方法的参数列表必须相同。
-
修饰符好,范围可以扩大:public->protected->Default->private
-
抛出的异常的范围,在子类可以被缩小,但不能扩大。ClassNotFoundException(小的)–>Exception(大的)。
为什么要重写:
1. 子类不一定需要父类的方法,或者父类方法不满足子类的需要。
//重写是方法的重写,和属性无关。
public class B {
public static void teststatic() {
System.out.println("B=>static");
}
public void test(){
System.out.println("B=>test");
}
}
public class A extends B {
public static void teststatic() {
System.out.println("A=>static");
}
//Override 重写
@Override//注解,重写
public void test() {
System.out.println("A=>TEST");
}
}
public class Aplication {
//静态方法和非静态方法区别很大!
//静态方法:方法的调用只和左边定义的类型有关系。
//非静态方法:子类重写了父类的方法。
public static void main(String[] args) {
//A是子类,B是父类。
//方法的调用只和左边定义的类型有关系
A a = new A();
a.teststatic();//调用的是子类的静态方法,结果:A=>static
a.test();//调用的是子类的方法,结果:A=>TEST
//父类的引用指向了子类
B b = new A();
b.teststatic();//调用的是父类的静态方法,结果:B=>static
b.test();//调用的是子类的方法,结果:A=>TEST
}
}
多态
注意点:
- 多态是方法的多态,属性没有多态。
- 父类和子类有联系。类型转换异常(ClassCastException)。
- 存 在 条 件 : 子 类 继 承 父 类 , 子 类 重 写 父 类 方 法 , 父 类 的 引 用 指 向 子 类 的 对 象 \color{red}{存在条件:子类继承父类,子类重写父类方法,父类的引用指向子类的对象} 存在条件:子类继承父类,子类重写父类方法,父类的引用指向子类的对象。
哪些方法不能被重写:
- static修饰的静态方法,属于类,它不属于实例。
- final 修饰的,是常量的,在常量池。
- private修饰的私有方法。
public static void main(String[] args) {
//一个对象的实际类型是确定的
//new Student();
//new Persion();
//可以指向的引用类型就不确定了:父类的引用指向子类
//子类能调用的方法都是自己的或者继承父类的
Student student=new Student();
//父类型,可以指向子类,但不能调用子类独有方法
Persion persion=new Student();//多态
Object object=new Student();
//能执行哪些方法,主要看左边的类型。
persion.print();//子类重写了父类的方法,那就执行了子类的方法。
((Student) persion).eat();//父类强转为子类类型,调用子类独有方法
}
使用继承性的结果就是当创建了一个类的家族,在认识这个类的家族时,就是把子类的对象当作基类的对象,这种认识又叫作upcasting(向上转型)。这样认识的重要性在于:我们可以只针对基类写出一段程序,但它可以适应于这个类的家族,因为编译器会自动找出合适的对象来执行操作。这种现象又称为多态性。而实现多态性的手段又叫称动态绑定(dynamic binding)。
简单的说,建立一个父类对象的引用,它所指对象可以是这个父类的对象,也可以是它的子类的对象。java中当子类拥有和父类同样的函数,当通过这个父类对象的引用调用这个函数的时候,调用到的是子类中的函数。
instance
public static void main(String[] args) {
//Object>String
//Object>Persion>Teacher
//Object>Persion>Student
Object object=new Student();
//Student继承Persion
//instanceof用来测试一个对象是否为一个类的实例
//x instanceof y
System.out.println(object instanceof Student);//true object属于学生类
System.out.println(object instanceof Persion);//true
System.out.println(object instanceof Object);//true
System.out.println(object instanceof String);//false
System.out.println("===========================");
Persion persion=new Student();
System.out.println(persion instanceof Student);//true
System.out.println(persion instanceof Persion);//true
System.out.println(persion instanceof Object);//true
//System.out.println(persion instanceof String);//编译报错
}
类型转换
- 父类引用指向子类对象。
- 把子类转换成父类,向上转型。
- 将父类转换成子类,向下转型,强制转换。
- 方便方法的调用,减少重复的代码。
封装,继承,多态 。类,抽象类,接口。
抽象:是一个编程思想。
public static void main(String[] args) {
//类型之间的转化:父 子
//高 低
Persion student=new Student();
//将student对象转化为Student类型,我们就可以使用Student类型的方法了!
Student student1=(Student)student;
//子类转换为父类,丢失自己的本来的方法。
Student student2=new Student();
Persion persion=student2;
}