Java 内部类种类及使用解析

内部类Inner Class

  将相关的类组织在一起,从而降低了命名空间的混乱。

  一个内部类可以定义在另一个类里,可以定义在函数里,甚至可以作为一个表达式的一部分。

  Java中的内部类共分为四种

  静态内部类static inner class (also called nested class)

  成员内部类member inner class

  局部内部类local inner class

  匿名内部类anonymous inner class

 

静态内部类Static Inner Class

  最简单的内部类形式。

  类定义时加上static关键字。

  不能和外部类有相同的名字。

  被编译成一个完全独立的.class文件,名称为OuterClass$InnerClass.class的形式。

  只可以访问外部类的静态成员和静态方法,包括了私有的静态成员和方法。

  生成静态内部类对象的方式为:

  OuterClass.InnerClass inner = new OuterClass.InnerClass();

  静态内部类使用代码:

静态内部类使用测试



package com.learnjava.innerclass;



class StaticInner

{

    private static int a = 4;



    // 静态内部类

    public static class Inner

    {

        public void test()

        {

            // 静态内部类可以访问外部类的静态成员

            // 并且它只能访问静态的

            System.out.println(a);

        }



    }

}



public class StaticInnerClassTest

{



    public static void main(String[] args)

    {

        StaticInner.Inner inner = new StaticInner.Inner();

        inner.test();

    }

}

  

成员内部类Member Inner Class

  成员内部类也是定义在另一个类中,但是定义时不用static修饰。

  成员内部类和静态内部类可以类比为非静态的成员变量和静态的成员变量。

  成员内部类就像一个实例变量。

  它可以访问它的外部类的所有成员变量和方法,不管是静态的还是非静态的都可以

  在外部类里面创建成员内部类的实例:

  this.new Innerclass();

  在外部类之外创建内部类的实例:

  (new Outerclass()).new Innerclass();

  在内部类里访问外部类的成员:

  Outerclass.this.member

  详情见代码例子:

成员内部类使用测试



package com.learnjava.innerclass;



class MemberInner

{

    private int d = 1;

    private int a = 2;



    // 定义一个成员内部类

    public class Inner2

    {

        private int a = 8;



        public void doSomething()

        {

            // 直接访问外部类对象

            System.out.println(d);

            System.out.println(a);// 直接访问a,则访问的是内部类里的a



            // 如何访问到外部类里的a呢?

            System.out.println(MemberInner.this.a);

        }



    }



}



public class MemberInnerClassTest

{



    public static void main(String[] args)

    {



        // 创建成员内部类的对象

        // 需要先创建外部类的实例

        MemberInner.Inner2 inner = new MemberInner().new Inner2();



        inner.doSomething();

    }

}

局部内部类Local Inner Class

  局部内部类定义在方法中,比方法的范围还小。是内部类中最少用到的一种类型。

  像局部变量一样,不能被public, protected, private和static修饰。

  只能访问方法中定义的final类型的局部变量。

(内部类并不是直接调用方法传进来的参数,而是内部类将传进来的参数通过自己的构造器备份到了自己的内部,自己内部的方法调用的实际是自己的属性而不是外部类方法的参数。  
这样理解就很容易得出为什么要用final了,因为两者从外表看起来是同一个东西,实际上却不是这样,如果内部类改掉了这些参数的值也不可能影响到原参数,然而这样却失去了参数的一致性,因为从编程人员的角度来看他们是同一个东西,如果编程人员在程序设计的时候在内部类中改掉参数的值,但是外部调用的时候又发现值其实没有被改掉,这就让人非常的难以理解和接受,为了避免这种尴尬的问题存在,所以编译器设计人员把内部类能够使用的参数设定为必须是final来规避这种莫名其妙错误的存在。简单理解就是,拷贝引用,为了避免引用值发生改变,例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用final来让该引用不可改变)

  局部内部类在方法中定义,所以只能在方法中使用,即只能在方法当中生成局部内部类的实例并且调用其方法。

局部内部类使用测试



package com.learnjava.innerclass;



class LocalInner

{

    int a = 1;



    public void doSomething()

    {

        int b = 2;

        final int c = 3;

        // 定义一个局部内部类

        class Inner3

        {

            public void test()

            {

                System.out.println("Hello World");

                System.out.println(a);



                // 不可以访问非final的局部变量

                // error: Cannot refer to a non-final variable b inside an inner

                // class defined in a different method

                // System.out.println(b);



                // 可以访问final变量

                System.out.println(c);

            }

        }



        // 创建局部内部类的实例并调用方法

        new Inner3().test();

    }

}



public class LocalInnerClassTest

{

    public static void main(String[] args)

    {

        // 创建外部类对象

        LocalInner inner = new LocalInner();

        // 调用外部类的方法

        inner.doSomething();

    }



}

匿名内部类Anonymous Inner Class

  匿名内部类就是没有名字的局部内部类,不使用关键字class, extends, implements, 没有构造方法。

  匿名内部类隐式地继承了一个父类或者实现了一个接口

  匿名内部类使用得比较多,通常是作为一个方法参数。

匿名内部类使用测试



package com.learnjava.innerclass;



import java.util.Date;



public class AnonymouseInnerClass

{



    @SuppressWarnings("deprecation")

    public String getDate(Date date)

    {

        return date.toLocaleString();



    }



    public static void main(String[] args)

    {

        AnonymouseInnerClass test = new AnonymouseInnerClass();



        // 打印日期:

        String str = test.getDate(new Date());

        System.out.println(str);

        System.out.println("----------------");



        // 使用匿名内部类

        String str2 = test.getDate(new Date()

        {

        });// 使用了花括号,但是不填入内容,执行结果和上面的完全一致

            // 生成了一个继承了Date类的子类的对象

        System.out.println(str2);

        System.out.println("----------------");



        // 使用匿名内部类,并且重写父类中的方法

        String str3 = test.getDate(new Date()

        {



            // 重写父类中的方法

            @Override

            @Deprecated

            public String toLocaleString()

            {

                return "Hello: " + super.toLocaleString();

            }



        });



        System.out.println(str3);

    }

}

 生成的.class文件中,匿名类会生成OuterClass$1.class文件,数字根据是第几个匿名类而类推。

你可能感兴趣的:(java 内部类)