第19讲
1 内部类简述
内部类就是在一个类中再定义一个类
-
在一个类A的内部定义一个类B,类B就被称为内部类
类A称之为外部类,类B称之为内部类,与这俩类无关的类都叫外部其他类
使用场景:内部类表示的事物是外部类的一部分,且内部类单独存在没有任何意义
- 如现要写一个汽车类,属性有:品牌,车龄,发动机,发动机的使用年限。
- 如果把这些属性全部写到汽车类里,这是不合理的,因为跟发动机相关的属性不应该跟车定义在一起。
- 如果把单独写一个发动机类,也不合理,因为发动机是依赖车存在的,单独出现没有任何意义。
public class Car {
String carName;
int carAge;
class Engine {
String engineName;
int engineAge;
}
}
分类:
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类(常用)
2 内部类访问特点
内部类访问外部类的成员
- 可直接访问,包括私有的
private
外部类访问内部类的成员
- 必须创建对象
3 匿名内部类(重要)
匿名内部类是一种隐藏了名字(不是没有名字)的特殊的局部内部类。
可以写在成员位置,也可以写在局部位置。
前提: 存在一个类(具体类、抽象类)或接口。
匿名内部类的本质是一个子类的匿名对象
- 子类继承了已存在的类,或者,子类实现了已存在的接口
格式:
new 类名或接口名() {
重写方法;
}; //注意这里是以分号结束
上述格式包含了继承或实现、方法重写、创建对象。
- 这个整体的本质是个对象;
- 大括号里才是真正的匿名类A,A实现(继承)了大括号前的接口(类);
- new创建的是A的对象,不是接口(类)的对象。
3.1 匿名内部类的使用
案例: 有接口Inter,现需要调用接口里的show方法
public interface Inter {
void show();
}
写法1
只能调用一次show()方法,每需要多调用一次就要复制一份以下代码。
public class Demo {
public static void main(String[] args) {
new Inter() {
@Override
public void show() {
System.out.println("匿名内部类");
}
}.show();
}
}
写法2
这样写,仅仅是创建一个对象,不能调用show方法。
public class Demo {
public static void main(String[] args) {
new Inter() {
@Override
public void show() {
System.out.println("匿名内部类");
}
};
}
}
写法3
采用多态的形式创建对象,可以多次调用。
public class Demo {
public static void main(String[] args) {
Inter i = new Inter() {
@Override
public void show() {
System.out.println("匿名内部类");
}
};
i.show();
i.show();
.....
}
}
3.2 匿名内部类的在开发中使用
//接口Jumpping
public interface Jumpping {
void jump();
}
//接口操作类,里面有一个方法,方法的参数是接口名
class JumppingOperator {
public void method(Jumpping j) {
j.jump();
}
}
现在如果要调用接口里的抽象方法,必须先创建接口操作类的对象。
但是接口要想实体化,必须参照多态的形式,所以需要以下步骤:
- 创建实现类,重写方法,实现接口
- 参照多态实体化创建对象
//1.创建实现类,重写方法,实现接口
public class Cat implements Jumpping {
@Override
public void jump() {
Sout: "猫跳的高";
}
}
public class Demo {
public static void main(String[] args) {
//2.参照多态实体化创建对象
JumppingOperator jo = new JumppingOperator();
Jumpping j = new Cat();
jo.method(j);
}
}
如果是多次调用接口里的抽象方法,用这种方式太过繁琐。
这时,就可以使用匿名内部类,不需要创建类就可以来实现接口。
public class Demo {
public static void main(String[] args) {
JumppingOperator jo = new JumppingOperator();
jo.method(new Jumpping() {
@Override
public void jump() {
Sout: "猫跳的高";
}
});
}
}
4 成员内部类
4.1 成员内部类简述
- 内部类在外部类的成员位置,属于外部类的成员,就叫成员内部类
- 成员内部类可以被权限修饰符和static修饰(如果用static修饰就是静态内部类)
- JDK16以后,成员内部类里可以定义静态变量
//外部类
public class Outer {
private int num = 10; // 私有成员变量
//成员内部类Inner
public class Inner {
public void show() {
System.out.println(num);//输出10,可以访问外部类私有属性
}
}
}
4.2 创建成员内部类对象
方式1
成员内部类用private
修饰。在外部类编写方法,对外提供内部类的对象
public class Outer {
private class Inner {
...
}
public Inner getInstance() {
return new Inner();
}
}
class Demo {
public static void main(String[] args) {
Outer o = new Outer();
//接收方式1:用成员内部类的父类接收(多态)
Object i = o.getInstance();
//接收方式2:不创建对象,直接用
System.out.println(o.getInstance());
}
}
方式2
成员内部类非私有。直接在外部其他类创建内部类对象
格式:外部类名.内部类名 对象名 = 外部类对象.内部类对象;
public class Outer {
public class Inner {
...
}
}
public class Demo {
public static void main(String[] args) {
//创建内部类对象
Outer.Inner oi = new Outer().new Inner();
}
}
4.3 成员内部类获取成员变量
外部类成员变量与内部类成员变量
-
不重名:直接
变量名
就可以获取 -
重名:
外部类名.this.变量名
public class Outer {
private int a = 10;
class Inner {
private int a = 20;
public void show() {
int a = 30;
System.out.println(Outer.this.a); //10
System.out.println(this.a); //20
System.out.println(a); //30
}
}
}
5 静态内部类
成员内部类的一种,用static修饰。
静态内部类只能访问外部类中的静态成员,如果想访问非静态需要创建外部类对象。
格式:
只要是静态的,都可以直接
类名.
获取
调用静态内部类里的:
-
静态方法:
外部类名.内部类名.方法名();
-
非静态方法:先创建对象,用对象调用
-
创建静态内部类对象:
外部类名.内部类名 对象名 = new 外部类名.内部类名();
public Outer {
static class Inner {
public void show1() {
System.out.println("静态内部类的非静态方法");
}
public static void show2() {
System.out.println("静态内部类的静态方法");
}
}
}
class Demo {
public static void main(String[] args) {
//创建静态内部类对象
Outer.Inner oi = new Outer.Inner();
//调用静态内部类里的非静态方法
oi.show1();
//调用静态内部类里的静态方法
//oi.show2(); //可以这么调,但是没有必要,也不提倡
Outer.Inner.show2();
}
}
6 局部内部类
内部类在类的局部位置(方法内),就叫局部内部类
注意:
- 外界无法直接使用局部内部类,如果要使用需要在方法内部创建对象,间接调用局部内部类
- 该类可以直接访问外部类的成员,也可以访问方法内的局部变量
public class Outer {
private int num = 10; // 私有成员变量
public void method() {
int age = 33;
// 局部内部类Inner
class Inner {
public void show() {
System.out.println(num); //可以直接访问外部类的成员
System.out.println(age); //可以访问方法内的局部变量
}
}
// 在方法内部创建对象,间接调用局部内部类
Inner i = new Inner();
i.show();
}
}