定义在一个类的内部的类叫内部类,包含内部类的类称为外部类。内部类可以声明public
、protected
、private
、defult
等访问限制,也可以声明为abstract
供其他内部类或外部类继承和扩展,也可以声明为static
、final
。本文主要是介绍成员内部类、静态内部类、局部内部类、匿名内部类以及成员内部类和静态内部类的区别。
成员内部类
成员内部类相当于外部类的一个成员,成员内部类可以直接访问外部类的所有(包括私有)成员属性和方法;外部类访问内部类的成员属性和方法,需要通过内部类的实例来访问。需要注意:成员内部类不能存在任何static
变量和方法,但 static final
的常量是可以的;原因:成员内部类是依赖于外部类的实例,而静态变量和方法不依赖对象的,在加载静态域时,外部类的实例还未创建,自然不行;但是常量在编译期就确定,放在常量池中。内部类中存在一个外部类的引用,可以用OuterClass.this
来指代。如果外部类和内部类具有相同的成员变量和方法,内部类默认访问自己的成员变量或方法,如果要访问外部类的成员变量或方法,需要显示指代,如OuterClass.this.attr/func()
。
静态内部类
静态内部类和外部类的对象没有关联。可以将静态内部类看成一个普通类,只是被声明在另一个类的内部。如果静态内部类被声明为private
,则该静态内部类只能在外部类中使用。静态内部类中不能直接访问外部类的非static
成员变量和方法。创建静态内部类的对象时不需要通过外部类的对象来进行。
局部内部类
局部内部类是嵌套在方法和作用域内,就像方法的一个局部变量。局部内部类是不能有public
、protected
、private
以及 static
等修饰符的,因为它的作用域被局限在声明这个局部类的块中。局部内部类除了可以访问外部类的成员以外,还可以访问它所在的作用域中的被final
修饰的局部变量。
匿名内部类
匿名内部类是对局部内部类的深化。匿名内部类不能定义任何静态方法或属性;不能定义抽象的方法,且必须实现接口或抽象父类的所有抽象方法。匿名内部类只能访问外部类的静态成员方法或属性。如果内部类继承父类或实现接口,可以不用内部类创建对象,直接将所需要的功能转化为匿名内部类的方法。
成员内部类与静态内部类的区别
1. 创建内部类对象的方式不同:静态内部类和普通静态类一样,直接new
一个对象实例,如StaticInnerClass staticInnerObj = new StaticInnerClass();
;成员内部类创建内部类对象需要先创建外部类对象,再通过外部类对象创建成员内部类的对象,如OutClassTest.InnerClass innerObj = new OutClassTest().new InnerClass();
。
2. 调用内部类的方法或属性的方式不同:调用静态内部类的方法和属性只需要用静态内部类的类名即可,调用成员内部类的方法和属性必须通过内部类的对象来调用。
3. 静态内部类只能访问外部类的静态方法或静态属性;成员内部类可以访问外部类的所有方法和属性。
4. 静态内部类可以定义静态方法和属性,成员内部类不能定义静态方法和属性,但可以定义static final
修饰的变量。
代码实现
1 | public class OutClassTest { |
总结
1. 每个内部类都能独立的继承一个类,无论外部类是否已经继承了某个类。
2. 内部类一般只为外部类使用,因此一般将内部类私有化(private
)。