重写
先来看以下代码:
// App.java
package com;
import com.A;
import com.B;
public class App {
public static void main(String[] args) {
// 下边调用:
// (1)如果调用的类方法;那么左边的数据类型决定最后的输出结果。
// (2)如果调用的是实例方法,这里边会存在一个子类重写父类的概念:
A a = new A();
B b = new A(); // 父类的引用可以指向子类
// 实例方法调用
a.test(); // "A"
b.test(); // "A"
// 类方法调用
a.t(); // "1"
b.t(); // "2"
}
}
// A.java
package com;
public class A extends B {
@Override
public void test() { System.out.println("A");}
public static void t() { System.out.println("1");}
}
// B.java
package com;
public class B {
@Override
public void test() { System.out.println("B"); }
public static void t() { System.out.println("2"); }
}
上边在App.java中分别引入A.java 和 B.java
(1)如果调用的是类方法,那么左边的数据类型决定最后的输出结果, 所以上边输出的是 "1"和"2", 结果不同。
(2)如果调用的是类中的实例方法,那么这里边存在一个子类重写父类的概念:
子类会重写父类的test方法,上边加上了 @Override注解, 类似python中的装饰器,表示子类重写了父类的方法。
java 中子类继承基类,可以重写基类中的方法,一般我们会定义 @Override 注解,那么是否可以不加 @Override 呢?
显然也可以!
对于java中是否添加 @Override 的区别在哪里呢?
写的情况下,表示子类覆盖基类中的方法,基类中必须存在该方法,控制器类型(public,protected,返回值,参数列表)与子类方法完全一致,否则会报错(找不到被 @Override 的方法)
不写的情况下,JVM也会自动识别,如果不满足完全一致的条件,则被当作新方法定义
加@Override的好处有利于编译器帮忙检测错误。
重写的前提
(1)重写的前提:
· 只能是子类继承父类时,子类重写父类的方法;
· 方法名必须相同;
· 参数列表必须相同, 这点非常重要;
· 修饰符可以的范围可以扩大,也就是说,如果父类时私有方法,那么子类可以用public来 把它继承过来( public > protected > default > private );
· 抛出的异常,范围可以被缩小,但不能被扩大;
(2)java 的重写只跟非静态方法有关系。
为什么需要重写
(1)父类的功能,子类不一定需要,或者不一定满足。
IDEA中重写的快捷键
Alt + Insert -> overide
多态
定义
同一方法,可以根据发送对象的不同,而采用多种不同的行为方法。一个对象的实际类型是确定的,但是可以指向对象的引用类型(一般指父类)有很多。
多态存在的条件
(1)存在继承关系;
(2)父类的引用指向子类的实例;
(3)子类重写父类的方法。
几个重点
(1)方法的多态,属性没有多态;
(2)存在的条件:继承关系,方法需要重写(子类和父类拥有相同的实例方法,方法体不一样,那么子类方法会重写父类的方法);
(3)父类的引用指向子类的对象;
(4)static类,final常量,private私有,不会重写,所以也不会存在多态的概念。
(5)多态是方法的多态,不是属性的多态。
(6)运行时,执行的方法,完全看左边的类型,由左边类型决定执行哪些方法。
// App.java
import com.Person;
import com.Student;
public class App {
public static void main(String[] args) {
Student stu = new Student();
Person per = new Student(); // 父类的引用指向了子类的实例(也就是子类实例类型也可以是父类类型,因为子类继承了父类)
// per是父类类型,但是子类重写了父类的test方法,所以输出 "student"
per.test(); // "student"
// per调用a方法,a方法只有子类才有,所以需要把per父类类型转化为Student类型,才能调用a方法
((Student) per).a(); // "aaaa"
// b方法只有父类有,所以输出 "bbbb"
per.b(); // "bbbb"
}
}
// Person.java 父类
package com;
public class Person {
public void test() { // test方法被子类重写了!
System.out.println("person");
}
public void b() {
System.out.println("bbbb");
}
}
// Student.java 子类
package com;
import com.Person;
public class Student extends Person{
@Override // 重写父类test方法
public void test() {
System.out.println("student");
}
public void a() {
System.out.println("aaaa");
}
}
instanceof
判断一个对象是否是某个类的实例,前提条件:两者需要有继承关系。
import com.Person;
import com.Student; // Student类继承Person类
public class App {
public static void main(String[] args) {
Student student = new Student();
System.out.println(student instanceof Person); // true
System.out.println(student instanceof Object); // true
}
}
类型转化
向上转型
向下转型