一.内部类
1.基本介绍
一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类(inner class),嵌套其他类的类称为外部类(outer class)。
2.内部类的分类
定义在外部类的局部位置上(比如方法内):
1)局部内部类
2)匿名内部类
2.定义在外部类的成员位置上
1)成员内部类(没用static修饰)
2)静态内部类(用static修饰)
3.基本语法
class Outer{ //外部类
class Inner{ //内部类
}
}
class Other{ //外部其他类
}
3.1 入门案例
public class InnerClass01 { //外部其他类
public static void main(String[] args) {
}
}
class Outer { //外部类
private int n1 = 100;//属性
public Outer(int n1) {//构造器
this.n1 = n1;
}
public void m1(){//方法
System.out.println("m1()");
}
{//代码块
System.out.println("代码块...");
}
class Inner { //内部类, 在 Outer 类的内部
}
}
4.局部内部类的使用
说明:局部内部类是定义在外部类的局部位置,比如方法中,并且有类名。
1.可以直接访问外部类的所有成员,包含私有的
2.不能添加访问修饰符,因为它的地位就是一个局部变量。局部变量是不能使用修饰符的。但是可以使用final修饰,因为局部变量也可以使用final
3.作用域:仅仅在定义它的方法或代码块中。
4.局部内部类–访问–>外部类的成损 [访问方式:[直接访问]
5.外部类–访问–>局部内部类的成员
访问方式:创建对象,再访问(注意:必须在作用域内)
记住:(1)局部内部类定义在方法中/代码块
(2)作用域在方法体或者代码块中
(3)本质仍然是一个类
6.外部其他类----不能访问---->局部内部类(因为局部内部类地位是一个局部变量)
7.如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名ths.成员)去访问
5.匿名内部类的使用
(1)本质是类 (2)内部类 (3)妆类没有名字 (4)同时还是一个对象说明:匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名
-
匿名内部类的基本语法new类或接口(参数列表){
类体
} -
匿名内部类的语法比较奇特,因为匿名内部类既是一个类的定义同时它本身也是一个对象,因此从语法上看,它既有定义类的特征,也有创建对象的特征,对前面代码分析可以看出这个特点,因此可以调用匿名内部类方法。
-
可以直接访问外部类的所有成员,包含私有的。
-
不能添动加访问修饰符,因为它的地位就是一个局部变量。
-
作用域:仅仅在定义它的方法或代码块中。
-
匿名内部类-访问–>外部类成员[访问方式:直接访问]
-
外部其他类-一一不能访问-一·>匿名内部类(因为匿名内部类地位是一个局部变量)
-
.如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,默认遵循就近原则如果想访问外部类的成员,则可以使用(外部类名.ths.成员)去访问
5.1 匿名类使用案例
public class AnonymousInnerClass {
public static void main(String[] args) {
Outer04 outer04 = new Outer04();
outer04.method();
}
}
class Outer04 { //外部类
private int n1 = 10;//属性
public void method() {//方法
//基于接口的匿名内部类
//1. tiger 的编译类型 ? IA
//2. tiger 的运行类型 ? 就是匿名内部类 Outer04$1
/* 底层 会分配 类名 Outer04$1
class Outer04$1 implements IA {
@Override
public void cry() {
System.out.println("老虎叫唤...");
}
}
*/
//3. jdk 底层在创建匿名内部类 Outer04$1,立即马上就创建了 Outer04$1 实例,并且把地址返回给 tiger
//4. 匿名内部类使用一次,就不能再使用
IA tiger = new IA() {
@Override
public void cry() {
System.out.println("老虎叫唤...");
}
};
System.out.println("tiger 的运行类型=" + tiger.getClass());
tiger.cry();
tiger.cry();
tiger.cry();
// IA tiger = new Tiger();
// tiger.cry()
//演示基于类的匿名内部类
//分析
//1. father 编译类型 Father
//2. father 运行类型 Outer04$2
//3. 底层会创建匿名内部类
/*
class Outer04$2 extends Father{
@Override
public void test() {
System.out.println("匿名内部类重写了 test 方法");
}
}
*/
//4. 同时也直接返回了 匿名内部类 Outer04$2 的对象
//5. 注意("jack") 参数列表会传递给 构造器
Father father = new Father("jack"){
@Override
public void test() {
System.out.println("匿名内部类重写了 test 方法");
}
};
System.out.println("father 对象的运行类型=" + father.getClass());//Outer04$2
father.test();
//基于抽象类的匿名内部类
Animal animal = new Animal(){
@Override
void eat() {
System.out.println("小狗吃骨头...");
}
};
animal.eat();
}
}
interface IA {//接口
public void cry();
}
//class Tiger implements IA {
// @Override
// public void cry() {
// System.out.println("老虎叫唤...");
// }
//}
//class Dog implements IA{
// @Override
// public void cry() {
// System.out.println("小狗汪汪...");
// }
//}
class Father {//类
public Father(String name) {//构造器
System.out.println("接收到 name=" + name);
}
public void test() {//方法
}
}
abstract class Animal { //抽象类
abstract void eat();
}
6.成员内部类的使用
说明:成员内部类是定义在外部类的成员位置,并且没有static修饰。
1.可以直接访问外部类的所有成员,包含私有的
2.可以添加任意访问修饰符(public、protected、默认、private),因为它的地位就是一个成员。
3.作用域和外部类的其他成员一样,为整个类体比如前面案例,在外部类的成员方法中创建成员内部类对象,再调用方法.
4.成员内部类–访问–一>外部类成员(比如:
属性)[访问方式:直接访问
5.外部类-访问–>成员内部类 访问方式:创建对象,再访问
6.外部其他类-访问-…>成员内部类
7.如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.ths.成员)去访问
7.静态内部类的使用
说明:静态内部类是定义在外部类的成员位置,并且有static修饰1.可以直接访问外部类的所有静态成损,包含私有的,但不能直接访问非静态成员
2.可以添加任意访问修饰符(public、.protected、默认、private),因为它的地位就是一个成员。
3.作用域:同其他的成员,为整个类体
4.静态内部类-访问–>外部类(比如:静态属性)访问方式:[直接访问所有静态成员]
5.外部类–访问–·->静态内部类访问方式:创建对象,再访问
6.外其他类–访问–>静态内部类
7.如果外部类和静态内部类的成员重名时,静态内部类访问的时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名成员)去访问