以下内容均来自:百度文库,略有改动.
1.内部类分类:
/* 内部类分类: ①成员内部类:实例内部类和静态内部类 ②局部内部类 ③匿名内部类
*/
2.成员内部类(定义在成员位置上)的实例内部类(非静态内部类)
① 在创建实例内部类的实例的时候,外部类的实例必须已经存在 Outer.InnerTools its = new Out().new InnerTools(); 以上代码等价于: Outer out = new Outer(); Outer.InnerTools its = out.new InnerTools(); ② 实例内部类的实例【自动】持有对外部类的实例的引用(Outer.this),所以在实例内部类中 可以直接访问外部类的[所有]成员(这里指的是外部类当中所有的public,protected,private,static的方法和成员变量) (可以理解为就是外部类中的成员与成员之间的访问) 之所以能访问,是因为在实例内部类中需要 先有外部类的实例,才能有内部类的实例. Outer.InnerTools its = new Outer().newInnerTools();
③ 在实例内部类中,外部类的实例与内部类的实例是一对多的关系,一个内部类实例 只会引用一个外部类实例,而一个外部类实例对应0个或n个内部类实例(可以有多个内部类),在外部类 中【不能】直接访问内部类的成员,必须通过内部类的实例去访问才可以。
class Outer
{
static int a=10;
class Inner
{
int i=3;
void method()
{
a=7;//可以
}
}}
class Demo
{
public static void main(String[] args)
{
new Outer().new Inner().method();}
}④在实例内部类中不能定义静态成员(和静态成员只能访问静态成员一个道理)
3.静态内部类:
(1) 静态内部类的实例【不会自动持有】外部类的实例的引用,在创建内部类的实例时,不必创建外部类的实例 //示例: Class A{ Public static class B{ Int v; } } Class Test{ Public void test(){ A.B b = new A.B(); b.v = 1; } } (2) 静态内部类可以直接访问外部类的静态成员,如果访问外部类的实例成员,就必须通过外部类的实例去访问 class A { private int a1; private static int a2; public static class B { //int b1 = a1; 错误 int b2 = a2;//0 int b3 = new A().a1;//0 } }
(3) 在静态内部类中可以定义静态成员和实例成员 class A { public static class B { int v1; static int v2; public static class C { static int v3; } } } (4) 外部类可以通过完整的类名来直接访问静态内部类的静态成员 class A { public static class B { int v1; static int v2; public static class C { static int v3; int v4; }; }; }; public class Client { public void test(){ A.B b = new A.B();//内部类B的实例 A.B.C c = new A.B.C();//内部类C的实例 b.v1 = 1;//通过实例访问B中非静态v1 b.v2 = 1;//通过实例访问B中静态v2 //A.B.v1 = 1//error A.B.v2 = 1; A.B.C.v3 = 1; } }
4.局部内部类:
局部内部类是在一个方法当中定义的内部类,它的可见范围是当前方法。和局部变量一样,局部内部类不能使用访问修饰符(public , private , protected) 以及 static来修饰, 局部内部类的特点是: (
1) 局部内部类只能在当前方法中使用. class A { //B b = new B();//error public void method(){ class B { int v1; int v2; class C { int v3; }; }; B b = new B(); B.C c = b.new C(); //可见B和C的作用作用域均在method方法体内 } } (2) 局部内部类和实例内部类一样,不能包含静态成员。 原因:(反证)如果可以包含->该内部类必须为static->而局部内部类不能被成员修饰符修饰 class A { public void method(){ class B { //static int v1;//error int v2; //static class C //error { int v3; } } } }
(3)在局部内部类中定义的内部类同样也不能被public protected, private这些访问修饰符修饰(局部内部类不能被public protectedprivate访问修饰符修饰) (4)
局部内部类和实例内部类一样,可以访问外部类的所有成员(包括外部类的静态成员:Outer.静态静态成员)(依然持有外部类引用:Outer.this),此外, 局部内部类还可以访问所在方法中的final类型的参数和变量(关于这一点我想另写一篇讨论) class A { int a; public void method(final int p1,int p2){ int localV1 = 1; final int localV2 = 2; class B { int b1 = A.this.a; int b2 = p1; //int b3 = p2;//error 不能访问,p2非finnal //int b4 = localV1//error 同理 int b5 = localV2; }; } }
5.匿名内部类(匿名子类对象):
(1) 匿名内部类本身没有构造器(无类名),但是会调用父类中的构造器。(相当于该匿名内部类实现了接口或继承一个类) public class A { A(int y){ System.out.println("不是默认构造器"); } A(){ System.out.println("默认构造器"); } void method(){ System.out.println("from A"); } public static void main(String[] args) { //new A().method();//默认构造器,from A A a = new A(){ void method(){ System.out.println("我是匿名内部类中的method方法"); } } //也就是说匿名构造器会自动调用父类中的构造器 a.method();//输出结果:默认构造器 我是匿名内部类中的method方法 } } (2) 匿名内部类尽管没有构造方法(因为没有类名),但是可以在匿名内部类中提供一段实例初始化代码(构造代码块),Java虚拟机会在调用了父类的构造方法之后,执行这段代码。 public static void main(String [] args){ int v = 1; A a = new A(v){ { System.out.println("init instance"); } void method(){ System.out.println("from anonymous"); } } a.method(); } 程序执行结果如下: another constructer//父类当中的构造器执行的结果 init instance from anonymous (3) 除了可以在外部类的方法内定义匿名类外,还可以在声明一个成员变量时定义匿名内部类。 abstract class A{ A a = new A(){ void method(){ System.out.println("inner"); } //把匿名内部类定义在了成员位置上 } abstract void method(); }
(4) 匿名内部类除了可以继承类外,还可以实现接口【重点】 Class Sample{ public static void main(String [] args){ Thread t = new Thread(new Runnable(){ public void run(){ for(int i = 0; i < 100; i++){ System.out.print(i); } } }); } } (5) 匿名内部类同局部内部类一样,可以访问外部类的所有成员,如果匿名内部类位于一个方法中,还能访问所在方法的final 类型的变量和参数 (6) 局部内部类和匿名内部类一样,名字在方法外都是不可见的,因此都可以起到封装类型名字的作用。