探讨JAVA内部类

来源:互联网 发布:java内部类可以用呢 编辑:程序博客网 时间:2024/05/21 09:09

*  内部类可以分为:成员内部类和局部内部类,而成员内部类又可以分为静态的成员内部类和非静态的成员内部类,而局部内部类就只有非静态的,没有静态的;

*  成员内部类:定义在一个类内部的类

首先来讨论非静态的成员内部类,这相当于类的非静态成员,因此可以用权限符来修饰,包括privateprotectedpublic;对于非静态的成员内部类,其创建方式分两种情况而定:

ü  如果方法是静态方法,那么创建非静态的成员内部类前就必须先创建外部类,基本语法是:

<外部类类名>.<内部类类名>  引用变量名称 = <外部类对象的引用>.new <内部类构造器>

<外部类类名>.<内部类类名> 引用变量名称 = new <外部类构造器>.new<内部类构造器>

ü  如果方法是非静态的方法,那么创建非静态内部类就可以按照普通的创建类的方法.

例如:

package test;

public class OutterClass {

   private class InterClass {

       private String s = "Non Static InterClass";

   }

   public void test() {//非静态方法

       System.out.println("--- 非静态方法调用非静态内部类 ---");

       InterClass ic = new InterClass();//普通方法创建

       System.out.println(ic.s);

   }

   public static void main(String[] args) {//静态方法

       //InterClass ic = new InterClass();//非法

       System.out.println("--- 静态方法调用非静态内部类 ---");

       OutterClass oc = new OutterClass();

       OutterClass.InterClass ic = oc.new InterClass();

//必须先创建外部类

       System.out.println(ic.s);

       oc.test();

   }

}

打印结果:

--- 静态方法调用非静态内部类 ---

Non Static InterClass

--- 非静态方法调用非静态内部类 ---

Non Static InterClass

内部类编译后生成的.class文件名称格式是<外部类类名>$<内部类类名>

内部类可以访问外部类的任何成员,包括private成员,例如:

package test;

public class OutterClass1 {

   private int i = 1;

   private class InterClass {

       public void test() {

           System.out.println("Visit The OutterClass member: " + i);

           //访问外部类的私有成员i,该成员也可以是静态的

       }

   }

   public static void main(String[] args) {

       OutterClass1.InterClass ic =

new OutterClass1().new InterClass();

       ic.test();

   }

}

打印结果:

Visit The OutterClass member: 1

而外部类访问内部类的成员需要创建内部类的对象,之后可以访问内部类的任何成员,包括private成员,需要注意的是非静态的成员内部类不可以有静态成员;但在静态的成员内部类中却是可以定义非静态成员的;如下是不允许的:

public class OutterClass {

    class InterClass {//非静态成员内部类
              static int i = 3;//不能定义了静态的成员变量;

            static void run() {
                         }//也不能定义静态的方法;
             }

}

当外部类的成员和内部类的成员重名时单单用this是区分不了的,在内部类中访问外部类的成员可以用如下语句:<外部类类名>.this.<外部类中需要被访问的成员名>

public class OutterClass {

       private int i = 1;

       private class InterClass {

           private int i = 2;

           public void run() {

               System.out.println(i);//打印的是内部类的成员变量i的值

               System.out.println(OutterClass.this.i);

//这个打印的才是外部类的成员变量i的值

           }

}

       public static void main(String[] args) {

           OutterClass oc = new OutterClass();

           OutterClass.InterClass ic = oc.new InterClass();

           //注意:直接InterClass ic = new InterClass();是不行的

           ic.run();

       }

}

打印结果:21

接下来我们来讨论静态的成员内部类,即用static修饰class

静态内部类的使用目的:在定义内部类的时候,可以在其前面加上一个权限修饰符

static。此时这个内部类就变为了静态内部类。如在进行代码程序测试的时候,如果在每一个Java源文件中都设置一个主方法(主方法是某个应用程序的入口,必须具有),那么会出现很多额外的代码。而且最主要的时这段主程序的代码对于Java文件来说,只是一个形式,其本身并不需要这种主方法。

但是少了这个主方法又是万万不行的。在这种情况下,就可以将主方法写入到静态内部类中,从而不用为每个Java源文件都设置一个类似的主方法。这对于代码测试是非常有用的。在一些中大型的应用程序开发中,则是一个常用的技术手段。

为此,这个静态内部类虽然不怎么常用,但是程序开发人员还必须要掌握它。也许在某个关键的时刻,其还可以发挥巨大的作用也说不定。

ü  只有将某个内部类修饰为静态类,然后才能够在这个类中定义静态的成员变量与成员

方法。这是静态内部类都有的一个特性。也正是因为这个原因,有时候少了这个静态的内部类,很多工作就无法完成。或者说要绕一个大圈才能够实现某个用户的需求。这也是静态的内部类之所以要存在的一个重要原因,例如:

package test;

public class OutterClass2 {

    private static class InterClass {

        private static int i = 1;//允许定义静态成员变量

        public static void test() {}//允许定义静态成员方法

    }

}

ü  如果一个内部类被定义为静态的,那么在引用外部类的成员方法或则成员变量的时

候,就会有诸多的限制。如不能够从静态内部类的对象中访问外部类的非静态成员(包括成员变量与成员方法)

这是什么意思呢?如果在外部类中定义了两个变量,一个是非静态的变量,一个是静态的变量。那么在静态内部类中,无论在成员方法内部还是在其他地方,都只能够引用外部类中的静态的变量,而不能够访问非静态的变量。

在静态内部类中,可以定义静态的方法(也只有在静态的内部类中可以定义静态的方法),在静态方法中引用外部类的成员。但是无论在内部类的什么地方引用,有一个共同点,即都只能够引用外部类中的静态成员方法或者成员变量。

对于那些非静态的成员变量与成员方法,在静态内部类中是无法访问的。这就是静态内部类的最大使用限制。在普通的非静态内部类中是没有这个限制的。

也正是这个原因,决定了静态内部类只应用在一些特定的场合。其应用范围远远没有像非静态的内部类那样广泛。如下是非法的:

public class OutClass {

   private int i = 1;

   private static class InterClass {

       public void run() {

           System.out.println(i);

//静态内部类不能访问外部类中的非静态成员变量

       }

   }

}

*  局部内部类:内部类定义在方法中称为局部内部类,只在局部有效,该类只为所在的

方法块服务。

局部内部类和成员内部类一样可以访问外部类的所有成员(不过要先new出一个外围类的实例),但是不可以访问同在一个局部块的普通局部变量,如果一定要访问,此局部变量要被声明为final

局部内部类不能使用权限符修饰,而只能使用finalabstract进行修饰;

局部内部类生成的.class文件是<外部类类名>$<n><内部类类名>其中n是该局部的第几个内部类;

下面是局部内部类的一个实例:

package test;

public class OutterClass4 {

    private int i = 1;

    public void test() {

       //int i = 2;

//这里可以重新定义i,但是后面内部类中调用i的时候就会以为调用的是局部的i而报错!

       int j = 2;

       class InterClass {

           public void test() {

              System.out.println(i);//合法,可以访问外部类的任何成员

              //System.out.println(j);//非法,不能访问局部的成员变量

           }

       }

    }

}

*  还有一种类,是和主类(与文件名相同的那个类)处在同一级别上的类,也是不能用权限符修饰的,可以使用finalabstract修饰,而主类则是一定要用public权限修饰的,这种类可以与成员内部类重名,但是调用的时候会优先调用成员内部类;

原创粉丝点击