一、什么是内部类?
将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。可以把内部类理解成寄生,外部类理解成宿主。
二、什么时候用到内部类?
一个事物内部还有一个独立的事物,内部的事物脱离外部的事物无法独立使用
例如:
- 人里面有一颗心脏。
- 汽车内部有一个发动机。
三、内部类的访问特点
- 内部类可以直接访问外部类的成员,包括私有。
- 外部类要访问内部类的成员,必须创建对象。
- 内部类如果想要访问外部类的成员变量,外部类的变量必须用final修饰,JDK8以前必须手动写final,JDK8之后不需要手动写,JDK默认加上。
-
内部类访问外部类对象的格式是:外部类名.this
四、内部类的分类
(一)、成员内部类
1、成员内部类特点:
- 写在成员位置的,无static修饰的内部类,属于外部类对象的。
- 可以被一些修饰符所修饰,比如:private , 默认 , protected , public 等。
- 在成员内部类里面,JDK16之前不能定义静态变量,JDK16开始才可以定义静态变量
2、内部类的使用格式:
外部类.内部类。 // 访问内部类的类型都是用 外部类.内部类
3、获取成员内部类对象的两种方式:
方式一:外部直接创建成员内部类的对象
外部类.内部类 变量 = new 外部类().new 内部类();
方式二:在外部类中定义一个方法,对外提供内部类的对象
示例:
// 方式一:外部直接创建成员内部类的对象
public class Test {
public static void main(String[] args) {
// 外部类对象。
//Outer out = new Outer();
// 创建内部类对象。
Outer.Inner oi = new Outer().new Inner();
oi.method();
}
}
public class Outer {
// 成员内部类,属于外部类对象的。
// 拓展:成员内部类不能定义静态成员。
public class Inner{
// 这里面的东西与类是完全一样的。
public void method(){
System.out.println("内部类中的方法被调用了");
}
}
}
// 方式二:在外部类中定义一个方法,对外提供内部类的对象
public class Outer {
String name;
class Inner{
int a = 10;
}
public Inner getInstance(){
return new Inner();
}
}
public class Test {
public static void main(String[] args) {
Outer o = new Outer();
// Object obj = o.getInstance();
// Outer.Inner instance = o.getInstance();
System.out.println(o.getInstance());
}
}
(二)、静态内部类
1、静态内部类特点:
- 静态内部类是一种特殊的成员内部类。有static修饰,属于外部类本身的。
- 静态内部类可以直接访问外部类的静态成员。
- 静态内部类不可以直接访问外部类的非静态成员,如果要访问需要创建外部类的对象。
- 静态内部类中没有隐含的Outer.this。
2、静态内部类对象的创建格式
外部类.内部类 变量 = new 外部类.内部类构造器;
例: Outer.Inner oi = new Outer.Inner();
3、调用静态内部类里的方法的格式:
非静态方法:先创建对象,用对象调用
静态方法:外部类名.内部类名.方法名();
示例:
// 外部类:Outer
public class Outer{
private static String name = "静态变量 ...";
// 内部类: Inner
public static class Inner{
private String name;
public Inner(String name) {
this.name = name;
}
public void showName(){
System.out.println(this.name);
System.out.println(Outer.name);
}
public static void method(){
System.out.println("静态方法 ... ");
}
}
}
public class Test {
public static void main(String[] args) {
// 创建静态内部类对象。
// 外部类.内部类 变量 = new 外部类.内部类构造器;
Outer.Inner oi = new Outer.Inner("张三");
oi.showName();
Outer.Inner.method();
}
}
(三)、局部内部类
1、局部内部类特点:
- 将内部类定义在方法里面就叫做局部内部类,类似于方法里面的局部变量
- 外界是无法直接使用,需要在方法内部创建对象并使用
- 该类可以直接访问外部类的成员,也可以访问方法内的局部变量
示例:
public class 外部类名 {
数据类型 变量名;
修饰符 返回值类型 方法名(参数列表){
// …
class 内部类名{
// 成员变量
// 成员方法
}
}
}
(四)、匿名内部类
1、匿名内部类的特点:
- 是内部类的简化写法。他是一个隐含了名字的内部类。开发中,最常用到的内部类就是匿名内部类。
- 这个类实现了父类,或者父类接口。(前提)
- 匿名内部类会创建这个没有名字的类的对象。
- 可以写在成员位置,也可以写在局部位置。
2、匿名内部类格式:
new 类名或者接口名(){
重写方法;
};
上面这段代码包含了:
- 继承或者实现关系
- 方法重写
- 创建对象
从语法上来讲,这个整体其实是匿名内部类对象
3、匿名内部类的使用场景
实际上,如果我们希望定义一个只要使用一次的类,就可考虑使用匿名内部类。匿名内部类的本质作用是为了简化代码