Java内部类和外部类讲解

内部类的位置:

 

       内部类可以作用在方法里以及外部类里,作用在方法里称为局部内部类,作用在外部类里分为实例内部类和静态内部类。

 

外部类和内部类的类访问修饰符:

 

       外部类可以是public和默认的,内部类可以是public,private,protected类型的

 

内部类和外部类的关系:

 

*在【实例内部类中】

    A:内部类可以访问外部类中所有的任何访问修饰符的成员。

    B:而一个外部类实例对应0个或n个内部类实例。在外部类中不能直接访问内部类的成员,必须通过内部类的实例去访问才可以

 

*在【静态内部类中】 

    A:静态内部类可以直接访问外部类的静态成员,如果访问外部类的实例成员,就必须通过外部类的实例去访问。在创建内部类的实例的时候,不必创建外部类的实例.

             B:外部类可以通过完整的类名来直接访问静态内部类的静态成员,如果要访问静态内部类的非静态成员则需要创建静态内部类的一个实例才行

 

package com.ming;

public class StaticInnerTest {

    public static class A{

        public int a = 10;

        static int b = 100;

    }

    public static void main(String[] args) {

        StaticInnerTest.A mya = new StaticInnerTest.A();

        mya.a = 1234;

        System.out.println(""+ mya.a);

    }

}

以上是可以运行成功的,已经经过测试

 

   *在【局部内部类中】

   A:局部内部类和实例内部类一样,可以访问外部类的所有成员

   B:外部类根本不知道局部内部类的存在,所以访问不了。

 

 

内部类的分类:

 

  1, 成员内部类(实例内部类,静态内部类)       |       2. 局部内部类

 

 

 

(一) 成员内部类(没有在方法中定义的内部类)

* (1)实例内部类:

 

    (1) 在创建实例内部类的实例的时候,外部类的实例必须已经存在

      

       Outer.InnerTools its = new Out().new InnerTools();

        以上代码等价于:

        Outer out = new Outer();

       Outer.InnerTools its = out.new InnerTools();

 

    (2) 实例内部类的实例【自动】持有对外部类的实例的引用,所以在实例内部类中

        可以直接访问外部类的[所有]成员(这里指的是外部类当中所有的publicprotected,private,static的方法和成员变量)

        之所以能访问,是因为在实例内部类中需要现有外部类的实例,才能有内部类的实例,参见(1).

       

       Outer.InnerTools its = new Outer().newInnerTools();

 

 

【注意:】在多重嵌套中,实例内部类可以访问所有外部类的成员

 

Class A{

Private void methodA(){}

 

Class B{

       Private void methodB(){}

      

      Class C{

         Private void MethodC(){

       methodA();

       methodB();

      } 

  }

 }

}

 

 

(3) 在实例内部类中,外部类的实例与内部类的实例是一对多的关系,一个内部类实例

只会引用一个外部类实例,而一个外部类实例对应0个或n个内部类实例,在外部类

中【不能】直接访问内部类的成员,必须通过内部类的实例去访问才可以。

 

(4) 在实例内部类中不能定义静态成员

 

 

* (2)静态内部类

     

(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;

              int b3 = new A().a1;

       };

}

 

 

 

 

 

(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();

              A.B.C c = new A.B.C();

              b.v1 = 1;

              b.v2 = 1;

              A.B.v1 = 1//error

              A.B.v2 = 1;

              A.B.C.v3 = 1;

       }

};

 

(二) 局部内部类 (在一个方法中定义的内部类)

 

局部内部类是在一个方法当中定义的内部类,它的可见范围是当前方法。和局部变量一样,局部内部类不能使用访问修饰符(public , private , protected) 以及 static 来修饰,局部内部类的特点是:

 

 

(1) 局部内部类只能在当前方法中使用.

 

 //www.infocool.net
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();

       }

}

 

(2) 局部内部类和实例内部类一样,不能包含静态成员。

 

class A

{

       public void method(){

              class B

              {

                     static int v1;//error

                     int v2;

 

                     static class C //error

                     {

                            int v3;

                     };

              };

 

       }

}

 

(3) 在局部内部类中定义的内部类同样也不能被public  protected, private这些访问修饰符修饰(局部内部类不能被public  protected  private访问修饰符修饰)

 

(4)  局部内部类和实例内部类一样,可以访问外部类的所有成员,此外,局部内部类还可以访问所在方法中的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;

                     int b2 = p1;

                     int b3 = p2;//error

                     int b4 = localV1//error

                     int b5 = localV2;

              };

       }

}

 

 


(三)  匿名内部类

 

匿名类是一种特殊的内部类,这种内部类没有自己的名字

 

(1) 匿名内部类本身没有构造器,但是会调用父类中的构造器。

 //www.infocool.net

package com.ming;

 

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)   匿名内部类除了可以继承类外,还可以实现接口【重点】

 

   Ccass 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) 局部内部类和匿名内部类一样,名字在方法外都是不可见的,因此都可以起到封装类型名字的作用。

 

 

【匿名内部类和局部内部类的区别】

 

   1,匿名内部类的程序代码量少

 

   2,一个局部内部类可以有多个重载构造方法,并且测试类可以多次创建局部内部类的实例。而匿名内部类没有重载构造方法之说,并且只能创建一次实例。

 

因此,如果只需要创建内部类的一个实例,可以使用匿名内部类,它能使程序代码简洁明了,如果需要多次创建内部类的实例,那么使用局部内部类。

 

                                          

转载请注明本文出处:http://blog.itpub.net/1700919/viewspace-2121911/

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/1700919/viewspace-2121911/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/1700919/viewspace-2121911/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值