“定义在另一个类中的类,即可以访问自身的数据域,也可以访问创建它的外围类对象的数据域,外围类想要访问内部类成员,必须创建对象”
_

为什么使用内部类?

  • 内部类方法可以访问改类定义所在的作用域中的数据,包括私有的数据
  • 内部类可以对同一个包中的其他类隐藏起来
  • 当想要定义一个回调函数且不想编写大量代码时,使用匿名(anonymous)内部类比较便捷

内部类对象总有一个隐式引用(此引用在内部类的定义中不可见),它指向了创建它的外部类对象。外围类的引用在构造器中设置,编译器修改了所有的内部类的构造器,添加一个外围类引用的参数,如果内部类没有定义构造器,那么编译器会为这个类生成一个默认的构造器。

创建对象语法规则

  1. //成员内部类不是静态的
  2. outerClass.InnerClass objectName = new outerClass.new InnerClass(construction parameters)
  3. //成员内部类是静态的
  4. outerClass.InnerClass objectName = new outerClass.InnerClass(construction parameters)

局部内部类

在一个方法中定义的局部类。局部类不能用public 或 private 访问说明符进行声明。它的作用域被限定在声明这个局部类的块中。它的优势是对外部完全隐藏,除声明它的方法之外,没有任何方法知道此类的存在。

  1. public class OuterClass
  2. {
  3. public void methodName()
  4. {
  5. public void InnerClass() {};
  6. InnerClass inner = new InnerClass();
  7. }
  8. }

匿名内部类

在一个方法中定义的没有类名的局部类,作用是只创建这个类的一个对象。SuperType 可以是接口,内部类就要实现这个接口;SuperType也可以是一个类,内部类就要扩展它

  1. //传递构造参数的小括号后面跟花括号就是匿名内部类
  2. new SuperType(construction parameters)
  3. {
  4. inner class methods and data
  5. }

由于构造器的名字必须与类名相同,而匿名类没有类名,所以匿名类不能有构造器。要将构造器参数传递给超类(superclass)构造器。在内部类实现接口的时候,不能有任何构造参数,还要提供一对括号。
匿名列表
双括号初始化,外层括号建立了ArrayList的一个匿名子类,内层括号是一个对象构造块。
当ArrayList 只执行一次性的时候可以使用双括号初始化

  1. new ArrayList<String>() {{ add("string"); add("string"); }};

获取静态方法的className:getClass() 可以获取当前方法所在类的类名,但是不能获取静态方法,因为调用 getClass() 时调用的是 this.getClass() ,静态方法没有 this,所以应该使用 :

  1. new Object(){}.getClass().getEnclosingClass();

静态内部类

当内部类不需要引用外部类对象,可以将内部类声明为 static,以便取消产生的引用。声明在接口中的内部类自动成为 static 和public 类