1 多态
多态:同类型的对象,执行同一个行为,会表现出不同的行为特征
优势
- 右边对象可以实现随意更改,更改后续业务只需改右边对象,其它代码无需更改,便于扩展和维护
- 定义方法时,使用父类型作为参数,该方法就可以接受这父类的一切子类对象
劣势:多态下不能使用子类的独有功能
常见形态
java
父类类型 对象名=new 子类构造器;
接口 对象名 = new 实现类构造器;
java
// 一般形态
Dog a = new Dog();
a.run()
Tortoise t= new Tortoise();
t.run();
// 多态(Dog和Tortoise都继承父类Animal)
Animal a = new Dog();
a.run()
Animal t= new Tortoise();
t.run();
多态中成员访问特点
|------|----------------------------------------------------|
| 方法调用 | 编译看左边(run方法在写代码时写的是Animal方法),运行看右边(运行的时候运行Dog里的方法) |
| 变量调用 | 编译看左边,运行也看左边(运行的时候变量值还是父类变量的值)。(多态侧重行为多态) |
强制类型转换
有继承关系/实现的两个类型就可以强制转换
作用:可以解决多态下的劣势,实现调用子类独有的功能
java
Animal a = new Dog();
a.run()
// 强制类型转换
Tortoise t = (Tortoise) a;
t.layEggs();
Animal t2 = new Tortoise();
Dog d = (Dog)t;//会出现异常
若转型后的类型与对象的真是类型不是同一个类型,会出现异常ClassCastException
解决办法:强制类型转换前用instanceof判断当前对象的真是类型,再转换
java
// 变量是否为真是类型,是返回true
变量名 instanceof 真实类型
2 内部类
内部类是定义在类里面的类
java
public class People{
public class Student{
}
}
使用场景、作用
- 当一个事物的内部,还有一部分需要一个完整的结构进行描述,这个完整的结构只外部事物用,那么这个内部的完整结构就可以选择使用内部类来设计
- 内部类通常可以方便访问外部类的成员,包括私有成员
- 内部类提供了更好的封装性,内部类本身可以用private,protected等修饰,封装性可以做更多的控制
静态内部类
有static修饰,属于外部类本身,它的特点和使用与普通类完全一样,类中有的成分也都具备,只是位置在类里面
java
public class People{
// 静态成员内部类
public static class Student{
}
}
// 静态内部类创建对象格式
People.Student s = new People.Student();
- 静态内部类可以直接访问外部类的静态成员,因为外部类的静态成员只有一份,可以共享
- 静态内部类不可以直接访问外部类的实例成员,因为外部类的实例成员必须外部类成员访问
成员内部类
无static修饰,属于外部类的对象,JDK16开始成员内部类可以定义静态成员
java
public class Outer{
public class Inner{
}
}
// 成员内部类创建对象格式
Outer.Inner in = new Outer().new Inner();
- 成员内部类可以直接访问外部类的静态成员,因为外部静态成员只有一份可以被共享访问
- 成员内部类的实例方法可以直接访问外部类的实例成员方法,因为必须现有外部类对象,才能有成员内部类对象,所以可以直接访问外部类对象的实例成员
若为了使用方便,定义为静态内部类;若希望访问外部类的所有成员,则定义为成员内部类
java
class People{
private int heartbeat = 150;
public class Heart{
private int heartbeat = 110;
public void show(){
int heartbeat = 78;
System.out.println(heartbeat); // 78
System.out.println(this.heartbeat); // 110
System.out.println(People.this.heartbeat); // 150
}
}
}
局部内部类
局部内部类放在方法、代码块、构造器等执行体中。
java
public class Test {
static {
//在代码块中定义
class C{
}
}
public static void main(String[] args) {
class A{
private String name;
public static int num = 100; // JDK 16开始支持。
public void show() {
}
}
A a = new A();
a.show();
}
public static void test(){
// 定义在普通方法中
class B{
}
}
}
匿名内部类*
本质上是一个没有名字的局部内部类,定义在方法、代码块等中
作用:方便创建子类对象,最终目的是为了简化代码编写
特点:匿名内部类没有名字,写出来会产生一个匿名内部类的对象。匿名内部类的对象类型相当于是当前new的那个类型的子类类型
java
public class Test1 {
public static void main(String[] args) {
// 匿名内部类的形式(Animal是抽象类不能调用,不用再创建子类了)
Animal a = new Animal(){
@Override
public void run() {
System.out.println("动物动物跑");
}
};
a.run();
}
}
abstract class Animal{
public abstract void run();
}