主要内容
- 内部类概述
- 成员内部类
- 局部内部类
- 匿名内部类
- 小结
一、内部类概述
1.1 内部类概念
将类写在其他类的内部,这时写在其他类内部的类就称为内部类(内置类,嵌套类),其他类也称为外部类。如:汽车和发动机
1.2 使用内部类的情况
若一个事物内部还包含其他可能包含的事物,如在描述汽车时,汽车中包含发动机,这时发动机就可以使用内部类来描述。
1.3 分类:
- 成员内部类
- 局部内部类(包含匿名内部类)
二、成员内部类
定义在外部类中的成员位置。与类中的成员变量相似,可通过外部类对象进行访问。
2.1 定义格式
修饰符 class 外部类名称 {
修饰符 class 内部类名称 {
// ...
}
// ...
}
2.2 访问方式
public class DemoInnerClass {
public static void main(String[] args) {
Body body = new Body(); // 外部类的对象
// 通过外部类的对象,调用外部类的方法,里面间接使用内部类Heart
body.methodBody();
Body.Heart heart = new Body().new Heart();
heart.beat();
}
}
public class InnerClass {
public static void main(String[] args) {
Outer.Inner obj = new Outer().new Inner();
obj.methodInner();
}
}
tips:
- 内用外,随意访问;外用内,需要内部类对象。
- 成员内部类可以使用的修符:
private,public,protected,final,static,abstract
三、局部内部类
局部内部类,定义在外部类方法中的局部位置。与访问方法中的局部变量相似,可通过调用方法进行访问
3.1 定义格式
修饰符 class 外部类名称 {
修饰符 返回值类型 外部类方法名称(参数列表) {
class 局部内部类名称 {
// ...
}
}
}
3.2 访问方式
如果一个类是定义在一个方法内部的,那么这就是一个局部内部类。
“局部”:只有当前所属的方法才能使用它,出了这个方法外面就不能用了。
3.3 代码实现
class Outer {
public void methodOuter() {
class Inner { // 局部内部类
int num = 10;
public void methodInner() {
System.out.println(num);
}
}
Inner inner = new Inner();
inner.methodInner();
}
}
四、 匿名内部类
如果接口的实现类(或父类的子类)只需使用唯一一次,那么这种情况下就可省略掉该类的定义,改为使用匿名内部类。
4.1 匿名内部类的定义格式:
接口名称 对象名 = new 接口名称() {
// 覆盖重写所有抽象方法
};
tips
对“new 接口名称() {…}”解析:
- new:创建对象
- 接口名称:匿名内部类需要实现哪个接口
- {…}:匿名内部类的内容
4.2 代码实现
public class Main {
public static void main(String[] args) {
MyInterface obj = new MyInterface() {
@Override
public void method() {
System.out.println("匿名内部类");
}
};
obj.method();
// 使用了匿名内部类,而且省略了对象名称,也是匿名对象
new MyInterface() {
@Override
public void method() {
System.out.println("匿名内部类");
}
}.method();
}
}
public interface MyInterface {
void method(); // 抽象方法
}
注意事项
- 匿名内部类,在创建对象时,只能使用唯一一次。
如果希望多次创建对象,而且类的内容一样的话,那么就需要使用单独定义的实现类了。 - 匿名对象,在调用方法时,只能调用唯一一次。
如果希望同一个对象,调用多次方法,那么必须给对象起个名字。 - 匿名内部类是省略了实现类/子类名称,但是匿名对象是省略了对象名称。
强调:匿名内部类和匿名对象不同!!!
五、小结
5.1 类的权限修饰符:
public > protected > (default) > private
5.2 定义一个类的时候,权限修饰符规则:
- 外部类:public / (default)
- 成员内部类:public / protected / (default) / private
- 局部内部类:什么都不能写
tips局部内部类,若希望访问所在方法的局部变量,那么这个局部变量必须是final的。
注意事项
从Java 8开始,只要局部变量不变,则final关键字可以省略。
原因:
- new出来的对象在堆内存当中。
- 局部变量是跟着方法走的,在栈内存当中。
- 方法运行结束之后,立刻出栈,局部变量就会立刻消失。
- new出来的对象会在堆当中持续存在,直到垃圾回收消失。