1.内部类定义: 可以将一个类的定义放在另一个类或者接口的定义内部.
2.内部类分类:
- 2.1 平凡的内部类:
- 2.2 嵌套类(static类型内部类)
- 2.3 匿名内部类
- 2.4 局部内部类(方法体代码块内的内部类)
3.1 对于平凡的内部类 :
形如
class Outter
{
void f(){};
void g(){};
class Inner{
void f()
{
Outter.this.f(); //OK
f(); // 无穷递归,因为调用的是自己的f()方法
g();//OK
}
}
}
从Inner类内部可访问Outter类的任何域和方法.通常平凡的内部类保存了一个对外部类的对象的引用.
3.2 对于嵌套类:
形如
class Outter
{
static class Inner{}
}
从Inner类内部可访问Outter类的静态域和静态方法,嵌套类并没保存对外部类的对象的引用.
3.3 匿名内部类: 同平凡的内部类
3.4 局部内部类: 同平凡的内部类,并且其可以访问包含其的外部类的方法体内定义的局部变量.
4.内部类的访问限制
4.1 对于平凡的内部类:其可能有四种类类型:public , protected , 包作用域 , private
除了private外,其他的三种类型的内部类都分别可以在不同的作用域被访问,若要构造一个内部类的实例
Outter outter = new Outter();//首先要生成一个外部类的引用
Outter.Inner inner = outter.new Inner();
注意两点;
- 1.内部类类名的引用形式: 外部类名.内部类名
- 2.构造形式: 外部类实例.new
对于private类型的平凡的内部类,可以通过工厂方式返回其引用,形式如下:
//step1:定义一个接口或类
interface X
{
void xx();
}
class Outter
{
private class Inner implements X{
void xx(){};
};
public static Inner getInner()
{
return new Inner();
}
}
//step2:获得内部类引用
X x = Outter.getInner();
平凡的内部类内部不能包含静态的域和方法.
4.2.1 无参数匿名内部类
class Outter
{
X getX()
{
return new X()
{
void xx(){};
};//注意此处需要加分号,否则给出编译时错误}}
4.2.2 有参数匿名内部类
//@exzample 1: final--needed;
class Outter{
X getX(final/*此处需用final类型指定,因为在内部类使用了变量i*/ int i)
{
return new X()
{
private int field1 = i;
void xx(){};
};//注意此处需要加分号,否则给出编译时错误}}
//@exzample 2: final--neededn't;
abstract Base{
protected String name ;
public Person(String name)
{this.name = name ; }
abstract void f();
}
class Outter{
Base getBase(/*Needn't be final ,for it is used in the scope of base class*/String name)
{
return new Base(name)
{
System.out.println(this.name);
}
}
}
在匿名内部不用使用构造函数,不过可以使用实例初始化,形如
class Outter{
X getX(final/*此处需用final类型指定,因为在内部类使用了变量i*/ int i)
{
return new X()
{
int field1;
{
field1 = i;
System.out.println("Hey , we can use the Instance Initialization "); }
void xx(){};
};//注意此处需要加分号,否则给出编译时错误}}
4.3 局部内部类: 与匿名内部类类似
5. 对于平凡内部类,生成的.class文件形如: 外部类名$内部类名.class
对于匿名内部类,生成的.class文件形如: 外部类名$x.class (其中x = 1,2 ,3....n)
对于局部内部类,生成的.class文件形如: 外部类名$x.内部类名.class