一、方法重写
1.1为什么进行需要方法重写?
当需要输出子类中独有的信息,此时父类中的方法不能够满足子类对象的使用
此时则需要对父类中相关方法进行重写以满足开发需要
1.2方法重写规则
1)方法名相同
2)参数列表相同
3)返回值类型相同或者是其子类,只能在子类重写
4)访问权限不能严于父类
5)父类的静态方法不能被子类覆盖为非静态方法,父类的非静态方法不能被子类覆盖为静态方法
6)子类可以定义与父类同名的静态方法,以便在子类中隐藏父类的静态方法(注:静态方法中无法使用super)
7)父类的私有方法不能被子类覆盖
8)不能抛出比父类方法更多的异常
1.3重写Object类中的toString()方法
在其他类没有重写toSting()方法之前,直接输出创建的对象名与输出对象名.toString()的结果是一样的,输出的都是对象的地址值,在其他类中输出对象的地址值没有太大的意义,此时对toString方法进行重写,让其输出对应的字符串以方便使用。
应用:当需要输出狗狗类相关信息时,就可以重写toString方法,这里可以直接使用系统默认重写
如果对输出不满意也可以进行修改。
public String toString() {
return "Dog [name=" + name + ", health=" + health + ", love=" + love
+ ", strain=" + strain + "]";
}
1.4重写Object类中的equals()方法
(1)Object类的equals()方法与==没区别,不能满足子类需求
(2)当有特殊需求,如认为属性相同即为同一对象时,需要重写equals()
(3)例如Java.lang.String就重写了equals()方法,把equals()方法的判断变为了判断其值
应用:重写equals方法用于判断当狗狗类昵称、品种、健康值相同时即可以认定为同一只狗狗
这里根据认定条件不同,可以更改代码进行区分
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Dog dog = (Dog) o;
return health == dog.health && Objects.equals(name, dog.name) && Objects.equals(strain, dog.strain);
}
二、多态
2.1多态的概念与作用
概念:同一个父类引用,指向不同的子类实例,执行不同的操作。
作用:频繁修改代码,代码可扩展性、可维护性差,使用多态优化
2.2多态实现步骤
1)在抽象父类中定义抽象方法
2)子类继承抽象父类并重写父类中所有的抽象方法
3)测试类中创建父类引用指向不同的子类实例,父类引用调用方法,调用的是子类重写后的那些方法
2.3向上转型与向下转型
1)向上转型即父类引用指向子类实例,类似于基本数据类型中的自动类型转换。
2)向下转型即子类引用指向父类实例,类似于基本数据类型中的强制类型转换。
当需要访问的方法是子类特有的方法时,需要用到向下转型,但是使用向下转型时可能出现类型转换异常,这时需要用到instanceof运算符进行判断。
例如:我们先创建一个抽象父类,在父类中创建一个抽象方法,再创建两个子类继承父类,并实现抽象方法。在测试类中创建对象,由于抽象父类无法创建对象,所以使用多态机制,向上转型指向子类实例。
Father father = new Son1("张三", 22, 173);
father.test();
father = new Son2("李四", 25, 160);
father.test();
再将创建后的father向下转型为Son1子类,通过son引用调用son中重写的方法
此代码编译没有问题,运行时系统在Son2类中找不到Son1Method()方法,因为此时还是Son2的实例,所以运行时会报错:类型转换异常,使用instanceof运算符进行判断就可以有效防止异常。
Son1 son = (Son1) father;
son.son1Method();
2.4instanceof运算符
第一: instanceof可以在运行阶段动态判断引用指向的对象的类型.
第二: instanceof的语法:(引用instanceof类型)
第三: instanceof运算符的运算结果只能是: true/false
第四: c是一个引用,c变量保存内存地址指向堆中的对象
假设(c instanceof cat)为true表示:c引用指向的堆内存中的java对象是一个cat
假设(c instanceof cat)为false表示:c引用指向的堆内存中的java对象不是一个cat
这里可以判断向下转型时的引用是谁,如果是Son1才会运行代码
if(father instanceof Son1){
Son1 son = (Son1)father;
son.son1Method();
}