一个类里面又完整地嵌套了另一个类结构。
成员属性、成员方法、构造器、代码块、内部类
内部类的特点内部类的最大特点就是可以直接访问私有属性
内部类的分类- 定义在外部类局部位置上(比如方法内)
- 通常定义在外部类的局部位置,通常在方法/代码块
- 不能加修饰符
- 能加final
加了final之后其他类不能继承它
- 作用域
仅仅在定义它的方法或者代码块中 - 内部类如何访问外部类:内部类可以直接访问外部类的所有成员,包含私有的
class OuterClass {
private int n1 = 1;
private void m(){};
public void out(){
// 局部内部类
// 定义在外部类的方法中,有类名
// 不能添加修饰符,但是可以用final修饰
final class innerClass1 {
public void print(){
// 内部类可以访问外部类的所有成员,包括私有的
System.out.println("n1=" + n1);
}
}
}
}
- 外部类如何访问内部类:在外部类的方法中,可以创建内部类对象,然后调用
public class InnerClass01 {
public static void main(String[] args) {
OuterClass outerClass = new OuterClass();
System.out.println("==============我即将调用OuterClass类的out方法==============");
outerClass.out();
}
}
// 外部类
class OuterClass {
private int n1 = 1;
private void m1() {
System.out.println("我是OuterClass类的m1()方法");
}
public void out() {
// 局部内部类
// 定义在外部类的方法中,有类名
// 不能添加修饰符,但是可以用final修饰
final class Inner1 {
public void print() {
System.out.println("我是内部类Inner1的print方法");
// 内部类可以访问外部类的所有成员,包括私有的
System.out.println("n1=" + n1);
// 调用了外部类的方法
m1();
}
}
// 在OuterClass类的out()创建Inner1类
Inner1 inner = new Inner1();
// 在外部类调用内部类的方法
System.out.println("==============我即将调用内部类的print方法==============");
inner.print();
}
}
结果:
我即将调用OuterClass类的out方法
我即将调用内部类的print方法
我是内部类Inner1的print方法
n1=1
我是OuterClass类的m1()方法
- 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,使用外部类名.this.成员名去访问
final class Inner1 {
private int n1 = 2;
public void print() {
System.out.println("我是内部类Inner1的print方法");
// 内部类可以访问外部类的所有成员,包括私有的
System.out.println("n1=" + n1);
// 调用了外部类的方法
m1();
System.out.println(n1); // 访问内部类的n1 = 2
System.out.println(OuterClass.this.n1); // 访问外部类的n1 = 1
}
}
匿名内部类(没有类名,重点)
- 本质是类
- 内部类
- 没有名字
- 同时也是一个对象
- 编译类型是写在左边的类
- 运行类型是匿名内部类
适用场景:这个类只用一次,后面不再使用,不想创建对象,这样可以简化开发。例如:当做实参直接传递
***注意:***匿名内部类只能适用一次,但是指向该类的对象可以多次使用
package annoy_;
public class Annoy {
public static void main(String[] args) {
B b = new B();
b.method();
}
}
interface IA {
public void cry();
}
class B {
public void method() {
// 创建匿名能内部类
// 实质是
// class B implements IA {
// @Override
// public void cry() {
// System.out.println("老虎嘤嘤嘤...");
// }
// }
IA tiger = new IA() {
@Override
public void cry() {
System.out.println("老虎嘤嘤嘤...");
}
};
// 对象可以多次使用
tiger.cry();
tiger.cry();
tiger.cry();
// 在jdk的底层,在创建匿名内部类时给了匿名内部类一个名字class annoy_.B$1,并且立刻创建了一个实例
System.out.println(tiger.getClass());
}
}
基于类的匿名内部类
// 此时底层解读为
// class B extends Father {
//
// }
// 这里的阿爹,阿往 会传给Father的构造器,不可以重写构造器
Father father1 = new Father("阿爹") {
};
Father father2 = new Father("阿往");
System.out.println(father1.getClass());
System.out.println(father2.getClass());
}
Father father1 = new Father("阿爹") {
};
Father father2 = new Father("阿往");
System.out.println(father1.getClass());
System.out.println(father2.getClass());
匿名内部类调用方法结果:
class annoy_.B$2
class annoy_.Father
7. 匿名内部类可以直接访问外部类的所有成员,包括私有的
8. 不能添加访问修饰符(它相当于一个局部变量)
9. 作用域:仅仅在定义它的方法或者代码块中
10. 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,使用外部类名.this.成员名去访问
package annoy_;
public class AnnoyDemo {
public static void main(String[] args) {
f1(new IB() {
@Override
public void show() {
System.out.println("hello");
}
});
}
// 静态方法,形参是接口类型
public static void f1 ( IB ib){
ib.show();
}
}
interface IB {
void show();
}
// 传统方法: 写一个类来实现IB,再new一个对象
- 定义在外部类的成员位置上
- 没有写在方法中
- 可以加修饰符,因为它的地位是一个成员
- 作用域:和其他成员一样,为整个类
- 成员内部类访问外部类:直接访问
- 外部类访问成员内部类:创建对象再访问
- 外部其他类访问成员内部类:
6.1 用外部类的对象new内部类的实例Father.Son son = new Father().new Son();
6.2 在外部类中写一个方法,返回内部类的对象
在成员内部类的基础上加了static
- 可以访问外部类的所有静态成员,但是不能直接访问非静态成员
2. 可以加修饰符
3. 作用域:为整个类体
4. 静态内部类访问外部类:直接访问所有静态属性
5. 外部类访问静态内部类:创建对象,再访问
6. 外部其他类访问静态内部类:
6.1 在满足访问权限的情况下,外部类.静态内部类,私有情况下;
6.2 编写方法,返回静态内部类的实例



