类的形式
在 Java 中除了前面提到的定义方式(形式)外还有一些其他的表现形式,至于原因个人的理解是便于对子类形成约束和管理
# 抽象类
当我们在做子类共性功能抽取时,有些方法在父类中并没有具体实现,或者说无法做出具体的实现,例如我们定义动物类并定义吃的这个功能,猫、狗、人同属于动物,但是具体吃的方式却不相同,此时就需要使用抽象类
抽象类的定义并不复杂,仅仅是在声明类的定义时增加 abstract 关键字修饰即可,抽象方法同理
public abstract class Animal{
public abstract void eat();
}
2
3
4
5
6
抽象类的特点
抽象类中可以没有抽象方法
有抽象方法的类必须是抽象类
子类继承抽象类时必须重写其抽象方法
抽象类不能实例化(创建对象)
这些特点也是我们在编写代码时必须遵循的规则
# 内部类
这种形式的类比较容易理解,即定义在类内部的类就称为内部类。我们知道在类的内部有两个比较重要的位置,即成员位置和局部位置。作为内部类而言它可以定义在这两个位置,同时因为位置的不同称呼也有所不同
# 成员位置
定义在此位置的类就是我们通常所说的内部类,作为一个类它在具备类本身特点的同时还具备类成员的一些特点,例如内部类可以访问其所在类的其他类成员
import com.coder163.User.PrimaryStudent;
public class User{
public void learn() {
System.out.println("学习");
}
public class Student{
public void demo1() {
learn();
}
}
public static class PrimaryStudent{
public void demo1() {
System.out.println("静态内部类");
}
}
}
public class Main {
public static void main(String[] args) {
User.Student us=new User().new Student();
us.demo1();
User.PrimaryStudent ups=new PrimaryStudent();
ups.demo1();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
代码解析
Student 类很明显是一个内部类,它可以访问 User 类中的任意成员(包括私有成员)
在不同类中引用内部类使用就如 main 方法中的使用方式,需要先创建外部类的对象其后在创建内部类对象
PrimaryStudent 为静态内部类,它同样遵循静态成员只能访问静态成员所以无法调用 User 类的非静态成员 learn 方法
在引用静态内部类时,哪怕在同一个包中也需要引包,目的是指定类的位置。同时可以不创建外部类对象
# 局部位置
此位置的内部类称为匿名内部类,应用场景并不是特别多。在 JDK1.8 引入 Lambda 表达式之后才有所改善
下面的代码仅做演示使用
public abstract class Animal{
public abstract void eat();
}
public class Demo2 {
public static void main(String[] args) {
Animal animal=new Animal() {
@Override
public void eat() {
System.out.println("HelloWorld");
}
};
animal.eat();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
代码解析
main 方法中创建的 Animal 对象其实并不是 Animal 类的对象,而是通过匿名内部类的形式继承 Animal 并创建匿名内部类的对象
animal 变量的类型只能是匿名内部类的父类类型,因为它本身并没有类型标识
因为匿名内部类所处的位置一般是方法的内部,这也就意味着我们在匿名内部类中不适合书写比较复杂或者篇幅较长的代码
# 小结
当我们定义或者声明一个方法而该方法的具体实现方式却各不相同时,抽象类很适合。
内部类适用的场景也有很多,例如我们在处理 Swing 编程中的监听器时通常都会适用内部类或者匿名内部类来完成