目录
多态
多态是指,针对某个类型的方法调用,其真正执行的方法取决于运行时期实际类型的方法。
Person p = new Student();
p.run(); //无法确定运行时究竟是调用哪个方法
意味着允许不同类的对象对同一消息作曲不同的响应。
分为
- 编译时多态:设计时多态
- 运行时多态:程序运行时动态决定调用哪个方法
必要条件:
- 满足继承关系
- 父类引用指向子类对象
向上转型和动态绑定机制
1.向上转型的概念:
向上转型又叫自动转型、隐式转型。向上转型是父类引用指向子类实例,也就是子类的对象可以赋值给父类的对象。
如:Animal dog =new Dog(); //Dog类是Animal类的子类
注:向上转型是安全的,因为任何子类都继承并接受了父类的方法。从例子中也可以理解,所有的狗狗都属于狗的父类——动物,这是可行的,但是向下转型则不行,若说所有动物都是狗狗就不成立了。(所以向下转型要通过强制类型转换)
2.向上转型的应用
- 当一个子类对象向上转型为父类对象,所能调用的方法会减少,只能调用子类重写父类的方法以及父类派生的方法(如set()、get()方法),而不能调用子类独有的方法。
例如:
对象实例化:
此时,调用方法调用时:
可以调用子类重写父类的方法writing(),但是调用子类独有的show()时就是无效的
2.父类中静态方法是不允许被子类重写的。
多态的实现可以通过向上转型和动态绑定机制来完成,向上转型实现了将子类对象向上转型为父类类型,二动态绑定机制能识别出对象转型前的类型,从而自动调用该类的方法,两者相辅相成。
动态绑定
绑定就是将一个方法调用同一个方法所在的类连接到一起就是绑定。绑定分为静态绑定和动态绑定两种。
- 静态绑定:在程序运行之前进行绑定(又编译器和链接程序完成的),也叫做前期绑定。
- 动态绑定:在程序期间又JVM根据对象的类型自动判断应该调用哪个方法,也叫做后期绑定。
静态绑定的例子:
动态绑定的例子
向下转型和instanceof运算符的应用
1.向下转型
2.向下转型后,可以调用子类自己独有的方法。
3.兄弟类之间不能进行强制类型转换。
instanceof 运算符
基本概念
如果左边对象是右边类的实例则返回true,否则返回false。
2.instanceof 的运用
抽象类和抽象方法
1.基本概念:
2.抽象类和抽象方法的声明格式
3.抽象类和抽象方法的特点
- 抽象类不允许直接实例化,换句话说抽象类不能创建对象,它只能作为其他类的父类。但可以通过向上转型,指向实例化
- 抽象方法只有声明,不能有实现,也就是仅有方法头,而没有方法体和操作实现。
- 如abstract double area();
4.定义抽象类的意义在于:
重点注意:
- 含有抽象方法的类,只能被定义成抽象类。
- 抽象类不一定包含抽象方法
- 在抽象类中成员方法可以包括一般方法和抽象方法
- 抽象类不能被实例化,即使抽象类里不包含抽象方法,这个抽象类也不能创建实例
- 抽象类的构造方法主要是用于被其子类调用
例子:
- 一个类继承抽象类后,必须实现其所有抽象方法,否则也是抽象类,不同的子类对父类的抽象方法可以有不同的实现。
- 即使父类是具体的,但其子类也可以是抽象的,如Object是具体的,但可以创建抽象子类。
- abstract方法不能用static和private修饰;对于类,不能同时用final和abstract修饰,因为final关键字使得类不可继承,而abstract修饰的类如果不可以继承就没有任何意义,两者放在一起,会起冲突
一个完整准确的抽象类例子
内部类
方法内部类
- 定义在方法内部,作用范围也在方法内
- 和方法内部类成员使用规则一样,class前面不可以添加public、private、protected、static
- 类中不能包含静态成员
- 类中可以包含final、abstract修饰的成员
成员内部类
- 内部类在外部使用时,无法直接实例化,需要借由外部类信息才能完成实例化
- 内部类的访问修饰符,可以任意,但是访问范围会受到影响
- 内部类可以直接访问外部类的成员;如果出现同名属性,优先访问内部类中定义的
- 可以使用外部类.this.成员的方式,访问外部类中同名的信息
- 外部类访问内部类信息,需要通过内部类实例,无法直接访问
- 内部类编译后.class文件命名:外部类$内部类.class
- 内部类中是否可以包含与外部类相同方法签名的方法?以及如何调用?
public class Heart1 {
int age = 13;
int temp = 22;
// public void eat(){....}
public String beat() {
eat();
return Person.this.age + "岁的心脏在跳动";
}
}
静态内部类
- 静态内部类中,只能直接访问外部类的静态成员,如果需要调用非静态成员,可以通过对象实例
- 静态内部类对象实例时,可以不依赖于外部类对象
- 可以通过外部类.内部类.静态成员的方式,访问内部类中的静态成员
- 当内部类属性与外部类属性同名时,默认直接调用内部类中的成员;
- 如果需要访问外部类中的静态属性,则可以通过 外部类.属性 的方式;
- 如果需要访问外部类中的非静态属性,则可以通过 new 外部类().属性的方式;
public static class Heart {
public static int age = 13;
int temp = 22;
public static void say() {
System.out.println("hello");
}
public void eat() {
}
public String beat() {
new Person().eat();
return Person.age + "岁的心脏在跳动";
}
}
匿名内部类
- 匿名内部类没有类型名称、实例对象名称
- 编译后的文件命名:外部类$数字.class
- 无法使用private、public、protected、abstract、static修饰
- 无法编写构造方法,可以添加构造代码块
- 不能出现静态成员
接口中的内部类
我们在实际开发过程中,如果想要创建某些公共代码,使得它们可以被某个接口的所有不同实现所共用,那么接口内部的嵌套类会显得很方便。也就是说,在接口中可以含有内部类。在这里,向大家展示接口中放置普通成员内部类和抽象成员内部类的情况。
匿名内部类