成员内部类(普通内部类)
1 | //外部类 |
Inner类相当于Outer类内部的一个成员,Inner类可以用任何访问修饰符。
Inner类中的test()方法可以不受限制地访问外部类中的数据,但是外部类不能直接访问内部类中的成员。
定义了内部类之后,必须使用外部类对象创建内部类,不能直接new内部类。
即:内部类 对象名 = 外部类对象.new 内部类();
注*:可以通过创建内部类对象,对象调用内部类成员的方法来实现外部类调用内部类的成员(main方法中的代码)。
上述程序编译之后会产生两个class文件“Outer.class”和“Outer$Inner.class”。
成员内部类的class文件总是:外部类$内部类.class
注*:Java 编译器在创建内部类对象时,隐式的把其外部类对象的引用也传了进去并一直保存着(先创建指向外部类的指针,再作为内部类构造函数的参数)。这样就使得内部类对象始终可以访问其外部类对象,同时这也是为什么在外部类作用范围之外想要创建内部类对象必须先创建其外部类对象的原因。
如果外部类有和内部类同名的成员变量或方法,内部类对象默认使用内部类的成员变量或方法。
注*:如果内部类对象想要调用外部类对象的变量或者方法,可以使用this关键字。
成员变量名(方法名)→调用内部类自身的。
this. 成员变量名(方法名)→调用内部类自身的。
外部类名.this.成员变量名(方法名)→调用外部类自身的。
如果外部类中的同名成员变量或方法被static关键字修饰,内部类中可以直接外部类.静态成员的方式范文。
普通内部类只能包含非静态变量、非静态方法、非静态类。
静态内部类
1 | //外部类 |
静态内部类不能直接访问外部类的非静态成员,但可以通过new 外部类().非静态成员名的方式访问。
如果外部类的静态成员和内部类的成员同名,内部类中可以外部类.静态成员的方式访问。如果外部类的静态成员和内部类的成员不同名,内部类中可以直接用静态成员名访问。
创建静态内部类时不需要外部类对象,可以直接创建静态内部类对象。
接口中的静态内部类作为接口的一部分来使用:
1
2
3
4
5
6
7
8public interface OutInterface {
// 在接口中定义的任何类都自动的是public和static的,因此这两个关键字都可以省略
class Inner {
public void print() {
System.out.println("print()");
}
}
}在接口中定义的任何类都自动的是public和static的,因此这两个关键字都可以省略。
静态内部类可以包含静态和非静态变量、静态和非静态方法、静态内部类和成员内部类。
《Java编程思想》(第四版,P203):
如果你想要创建某些公共代码,使得它们可以被某个接口的所有不同实现所共用,那么使用接口内部的静态内部类会显得很方便。
例:
1 | /** 接口*/ |
1 | /** 实现类 */ |