java学习(十)继承extends、方法覆盖、多态
继承语法
class 类名 extends 父类名{
类体;
}
- java中规定,子类继承父类,除构造方法不能继承之外,剩下的都可以继承。但是private修饰的私有属性无法在子类中直接访问。
方法覆盖:重写父类方法
- 中国人和美国人都继承人类,中国人调用打招呼希望输出“你好”,但是美国人调用打招呼希望输出“hi,hello”,这时候人类的到招呼方法就不满足需要了,需要方法覆盖。其实就是重写了父类方法。
代码:
public class People{
private String name;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
//定义一个方法
public void speakHi(){
System.out.println(this.name + "打个招呼");
}
}
public class ChinesePeople extends People{
public void speakHi(){
System.out.println("你好,我是 " + this.getName() + ",认识你很高兴");
}
}
public class AmericaPeople extends People{
public void speakHi(){
System.out.println("Hi,My name is:" + this.getName() + ",nice to meet you");
}
}
public class PeopleTest {
public static void main(String[] args) {
ChinesePeople cp = new ChinesePeople();
cp.setName("法外狂徒张三");
cp.speakHi();
AmericaPeople ap = new AmericaPeople();
ap.setName("tony");
ap.speakHi();
}
}
多态:其实就是同一个行为发生在不同的对象上会有不同的效果。
看Test01和Test02代码
public class Animal{
public void move(){
System.out.println("动物会移动");
}
}
public class Cat extends Animal{
//方法覆盖
public void move(){
System.out.println("猫会跑的!");
}
//猫特有方法
public void catchMouse(){
System.out.println("猫可抓老鼠!");
}
}
public class Bird extends Animal{
//方法覆盖
public void move(){
System.out.println("鸟会动的!");
}
//鸟特有的方法
public void fly(){
System.out.println("鸟飞了飞了!");
}
}
Test01.java:
public class Test01 {
public static void main(String[] args) {
//创建 Animal 对象
Animal a = new Animal();
a.move();
//创建 Cat 对象
Cat c = new Cat();
c.move();
c.catchMouse();
//创建鸟儿对象
Bird b = new Bird();
b.move();
b.fly();
}
}
Test02.java:
public class Test02{
public static void main(String[] args)
{
//向上转型
Animal a1 = new Cat();
a1.move();
//向上转型
Animal a2 = new Bird();
a2.move();
}
}
解释:在编译阶段编译 器只知道 a1 变量的数据类型是 Animal,那么此时编译器会去 Animal.class字节码中查找 move() 方法,发现 Animal.class 字节码中存在 move()方法,然后将该 move()方法绑定到 a1 引用上, 编译通过了,这个过程我们可以理解为“静态绑定”阶段完成了。紧接着程序开始运行,进入 运行阶段,在运行的时候实际上在堆内存中 new的对象是 Cat 类型,也就是说真正在 move 移 动的时候,是 Cat 猫对象在移动,所以运行的时候就会自动执行 Cat 类当中的 move()方法,这 个过程可以称为“动态绑定”。但无论是什么时候,必须先“静态绑定”成功之后才能进入“动 态绑定”阶段。
向上转型:自动类型转换
- java 中之所以有多态机制,是因为 java 允许一个父类型的引用指向一个子类型的对象。 这种父类型引用指向了子类对象属于向上转型,或者叫自动类型转换
向下转型:强制类型转换
- 如果想调用子类特有方法,就需要向下转型
public class Test04 {
public static void main(String[] args) {
//向上转型
Animal a = new Cat();
//a.catchMouse(); //编译报错
//向下转型:为了调用子类对象特有的方法
//强制类型转换将 Animal 类型的 a 引用转换成 Cat 类型的引用c
Cat c = (Cat)a;
c.catchMouse();
}
}
上面代码a.catchMouse();为什么报错呢?
那是因为“Animal a = new Cat();”在编译的时候,编译器只知道 a 变量的数据类型是 Animal,也就是说它只会去 Animal.class 字节码中查找 catchMouse()方法,结果没找到,自然“静态绑定”就失败了,编 译没有通过。就像以上描述的错误信息一样:在类型为 Animal 的变量 a 中找不到方法 catchMouse()。
类型转换异常
public class Test05 {
public static void main(String[] args) {
Animal a = new Bird();
Cat c = (Cat)a;
}
}
上述代码可以编译通过,原因是编译器只知道 a 变量是 Animal 类型,Animal 类和 Cat 类之间存在继承关系 ,所以可以进行向下转型 ,语法没问题,问题是运行的时候a引用指向实际是鸟啊,你强制转猫,就报错了。
运算符 instanceof:结果是布尔值,如果是true就可以转型,false就不可以转型。
instanceof 运算符 语法格式:
(引用 instanceof 类型)
代码:
public class Test05 {
public static void main(String[] args) {
Animal a = new Bird();
if (a instanceof Cat){ //判断引用a是不是Cat类型
Cat c = (Cat)a;
c.catchMouse();
}else if(a instanceof Bird){ //判断引用a是不是Bird类型
Bird b = (Bird)a;
b.fly();
}
}
}
其实多态存在的三个必要条件分别是:
① 继承
② 方法覆盖
③ 父类型引用指向子类型对象 ,子类将方法重写之后调用到子类对象上的 方法产生不同效果时,多态就形成了。