Java之内部类
内部类和外部类
定义在其他类的内部称为内部类,包含内部类的类被称为外部类,内部类是外部类的成员。
内部类的分类
1.静态内部类:有static修饰的成员内部类是静态内部类。
2.非静态内部类:没有static修饰的成员内部类是非静态内部类。
内部类的定义
1.非静态内部类:Java不允许在非静态类中定义静态Field,静态方法,静态初始化块。
2.静态内部类:可以包含静态Field,也可以包含非静态Field。
内部类的权限
1.非静态内部类(属于实例Field)
⑴.非静态内部类对外部类的权限
非静态内部类可以直接访问外部类的Field(包括private的Field),因为他是属于实例Field
⑵.外部类对非静态内部类的权限
可以通过显式创建非静态内部类对象来访问非静态内部类的Field,因为他是属于实例Field
public class Outer{ private int a = 3; // 外部类实例Field public class Inner{ private int b = 5; // 内部类实例Field public void acessOuter(){ // 内部类的实例Field方法 // 非静态内部类可以直接访问外部类的实例Field,因为都是实例Field System.out.println("外部类的a值:" + a); } } // 外部类实例Field方法 public void acessInner(){ // 通过显式创建非静态内部类对象来访问非静态内部类的实例Field Inner in = new Inner(); System.out.println("内部类的b值:" + in.b); } // main是Outer的类Field方法,不能访问非静态内部类,因为非静态内部类是属于实例Field public static void main(String[] args){ Outer ou = new Outer(); ou.acessInner(); // 通过调用外部类的实例Field来调用非静态内部类实例Field }}
2.静态内部类(属于类Field)
⑴.静态内部类对外部类权限
不可以访问外部类的实例Field,只能访问外部类的类Field(包括private的成员),因为他是属于类Field
⑵.外部类对静态内部类的权限
外部类不能直接访问静态内部类的Field,但可以使用静态内部类的类名作为调用者来访问静态内部
类的Field,也可以使用静态内部类对象作为调用者来访问静态内部类的实例Field。,因为他是属于类Field
public class Outer{ private int a = 3; // 外部类的实例Field private static int b = 5; // 外部类的类Field public static class s_Inner{ private int c = 70; // 内部类实例Field private static int d = 43; // 内部类的类Field // 内部类的实例Field方法 public void acessOuter(){ // 错误,静态内部类不可以直接访问外部类的实例Field // System.out.println("外部类的a值:" + a); // 静态内部类可以直接访问外部类的类Field System.out.println("外部类的b值:" + b); } // 内部类的类Field方法 public static void s_acessOuter(){ // 静态内部类的类Field方法不可以直接访问外部类的实例Field // 通过显式创建外部类实例来访问外部类的实例Field Outer ou = new Outer(); System.out.println("外部类的a值:" + ou.a); // 静态内部类的类Field方法可以直接访问外部类的类Field System.out.println("外部类的b值:" + b); } } // 外部类实例Field方法 public void acessInner(){ // 外部类实例Field方法不可以访问静态内部类的类Field // 必须显式创建内部类的实例才能访问内部类的实例Field s_Inner in = new s_Inner(); System.out.println("内部类的c值:" + in.c); // 外部类的实例Field方法可以访问静态内部类的类Field // 通过静态内部类的类名来访问静态内部类的类Field来访问 System.out.println("内部类的d值:" + s_Inner.d); } // main是Outer的类Field方法 public static void main(String[] args){ // 外部类的类Field方法可以访问静态内部类的类Field // 通过静态内部类的类名来访问静态内部类的类Field来访问 System.out.println("内部类的d值:" + s_Inner.d); // 外部类类Field方法不可以访问静态内部类的实例Field // 必须显式创建内部类的实例才能访问内部类的实例Field s_Innerin = new s_Inner(); System.out.println("内部类的c值:" + in.c); }}
3.在外部类以外访问内部类(包括静态内部类和非静态内部类)
⑴.使用private修饰的内部类不能被外部类以外的地方访问。
⑵.使用protected修饰的内部类,可被与外部类处于同一个包中的其他类和外部类的子类所访问。
⑶.使用public修饰的内部类,可以在任何地方被访问。
⑷.省略访问控制符的内部类,只能被与外部类处于同一个包中的其他类所访问。
⑸.在外部类以外的地方访问,必须使用内部类完整的类名。(例:包名.外部类类名.内部类类名)
静态内部类和非静态内部类对象的创建
1.非静态内部类
非静态内部类属于外部类实例Field,所以必须先构造外部类实例才能创建非静态内部类
Outer ou = new Outer(); // 必须现有外部类对象ou.Inner in = new Outer().new Inner(); // 创建非静态内部类对象
2.静态内部类
静态内部类是属于类Field,所以直接使用类名即可调用静态内部类的构造器
Outer.s_Inner in = new Outer.s_Inner();
非静态内部类的继承
创建非静态内部类的子类时,必须保证让子类构造器可以调用非静态内部类的构造器
public class innerSubClass extends Outer.Inner{ public innerSubClass(){ Outer.super();// 必须保证让子类构造器可以调用非静态内部类的构造器,super代表调用Inner构造器 } }
局部内部类
一个类放在方法里定义,则这个内部类就是一个局部内部类,局部内部类只有在该方法中有效,由于局部类的
访问范围只能在该方法中,所以不能使用访问控制符和static修饰
匿名内部类
只适合创建那种只需要一次使用的类。
匿名内部类规则
1.必须继承一个父类或实现一个接口。
2.只能继承一个父类或者实现一个接口。
3.不能是抽象类,因为系统创建匿名内部类时,会立即创建匿名内部类对象。
4.不能定义构造器,因为它没类名,但内部可以定义实例初始化块。
5.必须实现接口里的若干抽象方法。
6.必须实现抽象父类里的所有抽象方法。
从设计上看内部类
1.类中的内部类
由于类是物的抽象,内部类是物中子物的抽象,这个子物体无须与外部通信(最好是),只为了让整体物体
能更好的协调工作而存在。
2.局部内部类
局部内部类是存在于方法中,而方法是物的行为的抽象,自然局部内部类体现出进行行为中需要抽象的配件。
3.匿名内部类
是为了在软件抽象过程中产生的一次性物品而存在。