1.向上转型和向下转型
1.1向上转型
(1)实际就是创建一个子类对象,把它当做父类对象来使用
(2)子类对象是一个父类对象,即可以将一个子类对象当成父类对象来应用,因此,向上转型是安全的,因为是从小范围向大范围的转换
(3)使用场景:直接赋值、方法传参、方法的返回值
(4)优点:让代码实现更加灵活简单
(5)缺点:不能调用子类特有的方法
class Animal {
public String name;
public int age;
public void eat(){
System.out.println(this.name + "正在吃");
}
}
class Dog extends Animal {
public void swim(){
System.out.println(this.name + "正在游泳");
}
}
class Bird extends Animal {
public String wing;//翅膀
public void fly() {
System.out.println(this.name + "正在飞");
}
}
public class TextDame1 {
// 方法的参数
public static void eatAll(Animal animal){
animal.eat();
}
// 方法的返回值
public static Animal func(){
boolean a = true;
if (a){
return new Dog();
}else {
return new Bird();
}
}
public static void main(String[] args) {
Animal animal = new Dog();//直接赋值
// animal.swim();报错,不能调用子类特有的方法
Dog dog = new Dog();
eatAll(dog);//方法的参数
}
}
1.2向下转型
(1)不安全
(2)创建一个父类对象,将其当做子类对象来使用
class Animal {
}
class Dog extends Animal {
}
public class TextDame1 {
public static void main(String[] args) {
Dog dog1 = (Dog) new Animal();//不安全
}
}
2.重写
2.1重写的定义
(1)方法的重写是函数名相同,参数列表相同(包括类型和个数),返回值相同
(2)方法的重写也叫方法的覆盖、覆写
2.2规则
(1)子类在重写父类的方法时,必须与父类方法原型一致:修饰符、返回值类型、方法名(参数列表)要完全一致
(2)被重写的方法返回值类型可以不同,但是必须是具有父子关系的(协变类型)
(3)重写方法的访问修饰限定符必须大于等于被重写方法的访问修饰限定符
(4)被static、private修饰的方法、构造方法都不能被重写
(5)重写的方法, 可以使用 @Override 注解来显式指定,这样可以帮助我们进行检查以及提高代码的可读性
(6)被final修饰的方法不能被重写
(7)不要在构造方法中调用重写的方法
2.3重写和重载的区别
(1)方法的重写是函数名相同,参数列表相同(包括类型和个数),返回值相同;重载的函数名相同、参数列表不同、返回值不做要求
(2)重写发生在父子类之间;重载发生在同一个类中
(3)重写是实现了运行时的多态性;重载是实现了编译时的多态性
2.4动态绑定
(1)通过父类引用去引用子类对象,通过父类引用去调用父类和子类同名的覆盖方法,结果调用的是子类的方法
(2)动态绑定也称为后期绑定(晚绑定),即在编译时,不能确定方法的行为,需要等到程序运行时,才能够确定具体调用那个类的方法
class Animal {
public String name;
public int age;
public void eat(){
System.out.println("Animal的eat()方法");
}
}
class Dog extends Animal {
public void swim(){
System.out.println(this.name + "正在游泳");
}
// @Override是注解
@Override
public void eat() {
System.out.println("Dog的eat()方法");
}
}
public class TextDame1 {
public static void main(String[] args) {
Animal animal = new Dog();//直接赋值
animal.eat();
}
//结果:
// Dog的eat()方法
}
2.5静态绑定
(1)方法的重载就是静态绑定的典型代表
(2)也称为前期绑定(早绑定),即在编译时,根据用户所传递实参类型就确定了具体调用那个方法
3.多态
3.1定义
(1)通过一个引用调用方法之后可以有多种表型形式(以下面这个代码为例:animal是一个引用,通过animal这一个引用调用方法之后可以有多种表型形式,可以是dog的eat方法,也可以是bird的eat方法)
(2)多态体现:在代码运行时,当传递不同类对象时,会调用对应类中的方法
class Animal {
public void eat(){
System.out.println("Animal的eat()方法");
}
}
class Dog extends Animal {
// @Override是注解
@Override
public void eat() {
System.out.println("Dog的eat()方法");
}
}
class Bird extends Animal {
@Override
public void eat() {
System.out.println("Bird的eat()方法");
}
}
public class TextDame1 {
public static void eatAll(Animal animal){
animal.eat();
}
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat();
Bird bird = new Bird();
bird.eat();
}
//结果:
// Dog的eat()方法
// Bird的eat()方法
}
3.2实现条件
(1)必须在继承体系下
(2)子类必须要对父类中方法进行重写
(3)通过父类的引用调用重写的方法
3.3优缺点
优点:(1)能够降低代码的 “圈复杂度”, 避免使用大量的 if - else
(2)可扩展能力更强
缺点:代码的运行效率降低
package extendText;
class Shape {
public void draw(){
}
}
class Cycle extends Shape {
@Override
public void draw() {
System.out.println("画○");
}
}
class Rect extends Shape {
@Override
public void draw() {
System.out.println("画♦");
}
}
class Flower extends Shape {
@Override
public void draw() {
System.out.println("画❀");
}
}
public class DrawShape {
public static void shape(Shape shape){
shape.draw();
}
public static void main(String[] args) {
Cycle cycle = new Cycle();
cycle.draw();
Rect rect = new Rect();
rect.draw();
Flower flower = new Flower();
flower.draw();
}
}