“定义在另一个类中的类,即可以访问自身的数据域,也可以访问创建它的外围类对象的数据域,外围类想要访问内部类成员,必须创建对象”
_
为什么使用内部类?
- 内部类方法可以访问改类定义所在的作用域中的数据,包括私有的数据
- 内部类可以对同一个包中的其他类隐藏起来
- 当想要定义一个回调函数且不想编写大量代码时,使用匿名(anonymous)内部类比较便捷
内部类对象总有一个隐式引用(此引用在内部类的定义中不可见),它指向了创建它的外部类对象。外围类的引用在构造器中设置,编译器修改了所有的内部类的构造器,添加一个外围类引用的参数,如果内部类没有定义构造器,那么编译器会为这个类生成一个默认的构造器。
创建对象语法规则
//成员内部类不是静态的
outerClass.InnerClass objectName = new outerClass.new InnerClass(construction parameters)
//成员内部类是静态的
outerClass.InnerClass objectName = new outerClass.InnerClass(construction parameters)
局部内部类
在一个方法中定义的局部类。局部类不能用public 或 private 访问说明符进行声明。它的作用域被限定在声明这个局部类的块中。它的优势是对外部完全隐藏,除声明它的方法之外,没有任何方法知道此类的存在。
public class OuterClass
{
public void methodName()
{
public void InnerClass() {};
InnerClass inner = new InnerClass();
}
}
匿名内部类
在一个方法中定义的没有类名的局部类,作用是只创建这个类的一个对象。SuperType 可以是接口,内部类就要实现这个接口;SuperType也可以是一个类,内部类就要扩展它
//传递构造参数的小括号后面跟花括号就是匿名内部类
new SuperType(construction parameters)
{
inner class methods and data
}
由于构造器的名字必须与类名相同,而匿名类没有类名,所以匿名类不能有构造器。要将构造器参数传递给超类(superclass)构造器。在内部类实现接口的时候,不能有任何构造参数,还要提供一对括号。
匿名列表
双括号初始化,外层括号建立了ArrayList的一个匿名子类,内层括号是一个对象构造块。
当ArrayList 只执行一次性的时候可以使用双括号初始化
new ArrayList<String>() {{ add("string"); add("string"); }};
获取静态方法的className:getClass() 可以获取当前方法所在类的类名,但是不能获取静态方法,因为调用 getClass() 时调用的是 this.getClass() ,静态方法没有 this,所以应该使用 :
new Object(){}.getClass().getEnclosingClass();
静态内部类
当内部类不需要引用外部类对象,可以将内部类声明为 static,以便取消产生的引用。声明在接口中的内部类自动成为 static 和public 类