`
sunguanxing
  • 浏览: 1084359 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JAVA内部类

阅读更多
http://hi.baidu.com/kiddoneal/blog/item/3b6a68864fd75a20c75cc348.html


在java语言中,有一种类叫做内部类(inner class),也称为嵌入类(nested class),它是定义在其他类的内部。内部类作为其外部类的一个成员,与其他成员一样,可以直接访问其外部类的数据和方法。只不过相比较外部类只有public和默认的修饰符不同,内部类作为一个成员,可以被任意修饰符修饰。编译器在编译时,内部类的名称为OuterClass$InnerClass.class 。


1、内部类访问数据变量
当在某些时候,内部类中定义的变量与外部类中变量名称相同时,如何确保正确地访问每一个变量呢?

1.1在main中直接从外部类调用内部类的方法

class Outer
{
    private int index = 10;
    class Inner
    {
        private int index = 20;
        void print()
        {
            int index = 30;
            System.out.println(this); // the object created from the Inner
            System.out.println(Outer.this); // the object created from the Outer
            System.out.println(index); // output is 30
            System.out.println(this.index); // output is 20
            System.out.println(Outer.this.index); // output is 10
        }
    }

    void print()
    {
        Inner inner = new Inner();//得到内部类的引用
        inner.print();
    }
}

class Test
{
    public static void main(String[] args)
    {
        Outer outer = new Outer();
        outer.print();
    }
}
在这里内部类Inner中关键字this指向内部类Inner的对象,如果要想指向外部类的对象,必须在this指针前加上外部类名称,表示this是指向外部类构造的碎屑,如Outer.this 。

1.2在main中显式返回内部类引用

class Outer
{
    private int index = 10;
    class Inner
    {
        private int index = 20;
        void print()
        {
            int index = 30;
            System.out.println(index);
            System.out.println(this.index);
            System.out.println(Outer.this.index);
        }
    }

    Inner getInner()
    {
        return new Inner();//返回一个内部类的引用
    }
}

class Test
{
    public static void main(String[] args)
    {
        Outer outer = new Outer();
        Outer.Inner inner = outer.getInner();
        inner.print();
    }
}
Inner是Outer的内部类,所以在类Test中必须用属性引用符来标识出内部类。

1.3当main方法在Outer类内部

class Outer
{
        private int index = 10;
        class Inner
        {
             private int index = 20;
             void print()
             {
                  int index = 30;
                  System.out.println(index);
                  System.out.println(this.index);
                  System.out.println(Outer.this.index);
             }
        }

        Inner getInner()
        {
             return new Inner();//返回一个内部类的引用
        }

        public static void main(String[] args)
        {
             Outer outer = new Outer();
             Inner inner = outer.getInner(); // 注意此处变化
             inner.print();
        }
}
因为main方法在Outer内部,故可以直接引用,不需要属性引用符。


1.4在main方法中直接产生内部类对象

class Test
{
        public static void main(String[] args)
        {
             Outer outer = new Outer();
             Outer.Inner inner = outer.new Inner(); // 注意此处变化
             inner.print();
        }
}
在利用new构造方法构造一个外部类对象时,并没有连带着构造一个内部类对象,故需要访问内部类方法时,必须使用new操作符为这个外部类对象再构造一个内部类对象。

2、局部内部类
在方法中定义的内部类是局部内部类,它只能访问方法中的final类型的局部变量,因为用final定义的局部变量相当于是一个常量,延长了其生命周期,使得方法在消亡时,其内部类仍可以访问该变量。另外,它同样也可以引用定义在外部类的变量和方法。而且方法体中的局部内部类不允许有访问修饰符。

class Outer
{
        int num=10;
        public void print(final int aArgs)
        {
             class Inner
             {
                 int num=20;
                 public Inner()
                 {
                     System.out.println("This is Inner.");//此句可看出它与匿名内部类用法的不同。
                 }

                 public void print()
                 {    
                     int num=30;
                     System.out.println(this); // the object created from the local Inner
                     System.out.println(num);
                     System.out.println(this.num);
                     System.out.println(Outer.this.num);
                     System.out.println(aArgs);
                 }
             }
             Inner inner=new Inner();//此句必须放在定义类Inner的后面
             inner.print();
        }

        public static void main(String[] args)
        {
             Outer outer=new Outer();
             outer.print(40);
        }
}
对于局部类的命名,不管是在一个方法中定义多个类还是在几个方法中分别定义类,其编译后命名是:OuterClass$1InnerClass.class

3、匿名内部类
匿名内部类作为一种特殊的内部类,除了具有普通内部类的特点,还有自己的一些独有特性:
匿名内部类必须扩展一个基类或实现一个接口,但是不能有显式的extends和implements子句;
匿名内部类必须实现父类以及接口中的所有抽象方法;
匿名内部类总是使用父类的无参构造方法来创建实例。如果是实现了一个接口,则其构造方法是Object();
匿名内部类编译后的命名为:OuterClass$n.class,其中n是一个从1开始的整数,如果在一个类中定义了多个匿名内部类,则按照他们的出现顺序从1开始排号。

abstract class A
{
    abstract public void sayHello();
}

class Outer
{
    public static void main(String[] args)
    {
         new Outer().callInner(new A()
         {
               public void sayHello()
               {
                     System.out.println(this); // the object created from the anonymous Inner
                     System.out.println("Hello!");
               }
         });
    }

    public void callInner(A a)
    {
        a.sayHello();
    }
}

4、静态内部类
和非静态内部类相比,区别就在于静态内部类没有了指向外部类的引用。除此之外,在任何非静态内部类中,都不能有静态数据,静态方法或者又一个静态内部类(内部类的嵌套可以不止一层)。不过静态内部类中却可以拥有这一切。这也算是两者的第二个区别吧。一个静态的内部类,才可以声明一个static成员,静态内部类可以访问外围类的静态方法、成员(包括private static的成员)。静态内部类实例化的时候不必先实例化外围类,可以直接实例化内部类。而对于非静态内部类则必须先实例化其外部类,才能再实例化本身。

5.内部类的继承
当一个类继承自一个内部类时,缺省的构造器不可用。必须使用如下语法:
class WithInner
{
    class Inner
    {
        public void sayHello()
        {
            System.out.println("Hello.");
        }
    }
}

public class Test extends WithInner.Inner
{
    Test(WithInner wi)
    {
        wi.super();
    }
    public static void main(String[] args)
    {
        WithInner wi=new WithInner();
        Test test=new Test(wi);
        test.sayHello();
    }
}
因为每一个内部类都有一个指向外部类的引用,在继承一个内部类,必须先创建一个外部类,通过这个外部类引用来调用其内部类的构造方法。如果继承的内部类是一个静态内部类,则就不需要这样,直接super()调用即可;

6、内部类的2种特殊用法
一个类从另一个类派生出来,又要实现一个接口。但在接口中定义的方法与父类中定义的方法的意义不同,则可以利用内部类来解决这个问题。
interface Machine
{
    void run();
}

class Person
{    
    void run()
    {
        System.out.println("run");
    }
}

class Robot extends Person
{
    private class MachineHeart implements Machine
    {
        public void run()
        {
            System.out.println("heart run");
        }
    }

    Machine getMachine()
    {
        return new MachineHeart();
    }
}

class Test
{
    public static void main(String[] args)
   {
        Robot robot = new Robot();
        Machine m = robot.getMachine();
        m.run();
        robot.run();
    }
}
在Robot类内部使用内部类MachineHeart来实现接口Machine的run方法。同时Robot类又继承了父类Person的run方法。如果不使用内部类MachineHeart而使Robot直接实现接口Machine,则该如何调用父类的run方法?

利用内部类可解决c++中多重继承所解决的问题
class A
{
    void fn1()
    {
        System.out.println("It' s fn1.");
    }
}

abstract class B
{
    abstract void fn2();
}

class C extends A
{
    B getB()
    {
        return new B()
        {
            public void fn2()
            {
                System.out.println("It' s fn2.");
            }
        };
    }
}

class Test
{
    public static void main(String[] args)
    {
        C c = new C();
        c.fn1();
        c.getB().fn2();
    }
}
类C既要继承类A又要继承类B,则可将类B的定义放入类C内部,使之成为内部类。


一般情况下 当我们需要在某一情形下实现一个接口,而在另一情形下又不需要实现这个接口时,我们可以使用内部类来解决这一问题。让内部类来实现这个接口。另外一个很好的理由是java内部类加上接口可以有效地实现多重继承。

分享到:
评论

相关推荐

    浅谈Java内部类的四个应用场景

    Java内部类是Java言语的一个很重要的概念,《Java编程思想》花了很大的篇幅来讲述这个概念。但是我们在实践中很少用到它,虽然我们在很多时候会被动的使用到它,但它仍然像一个幕后英雄一样,不为我们所知,不为我们...

    java内部类详解

    java内部类详解

    Java内部类总结

    Java内部类总结 学习java的资源

    Java内部类应用详解

    从Java1.1开始引入了内部类以来,它就引起了人们的激烈争论。其实任何优秀的语言特性用得不好就是滥用,内部类用得不好就会导致代码像迷宫一样,导致出现毫无重用的综合征。...本文档讲述Java内部类的规则及应用

    12.java内部类.zip

    12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类.zip12.java内部类...

    java内部类的讲解

    这里是自己对java内部类整理的一篇文章,有可执行的源代码

    java内部类使用例子

    java内部类使用例子,可以运行

    Java内部类的四个应用场景

    谈Java内部类的四个应用场景

    java 内部类应用

    java 内部类应用java 内部类应用java 内部类应用java 内部类应用java 内部类应用java 内部类应用java 内部类应用java 内部类应用java 内部类应用java 内部类应用

    Java 内部类

    Java 的使用 分别介绍了 成员内部类、方法内部类、静态内部类

    Java内部类(DOC)

    Java内部类Java内部类Java内部类Java内部类Java内部类Java内部类Java内部类

    java 内部类 局部内部类 匿名类 实例代码

    java 内部类 实例内部类 局部内部类 匿名类 静态内部类 实例代码

    JAVA 内部类 PPT

    详细介绍JAVA内部类的用法,用途,基本语法,及匿名类用法

    Java内部类的作用

    Java内部类的作用

    JAVA内部类总结

    JAVA内部类的一些总结

    JAVA内部类.doc

    对内部类不错的讲解,以及如何应用并且还帮你归了类,不错的选择

    java内部类

    高效的课件,详细的内容介绍,针对性的代码展示,提高性的练习题目。适合新手或者基础薄弱人员学习,一个PPT解决你编程中常见的错误,最重要的是一人下载多人使用,不受限制,没有隐藏密码

    Java 干货之深入理解Java内部类(学习资料)

    Java 干货之深入理解Java内部类;Java 干货之深入理解Java内部类;Java 干货之深入理解Java内部类;Java 干货之深入理解Java内部类;Java 干货之深入理解Java内部类;

    java基础java内部类

    java基础java内部类

Global site tag (gtag.js) - Google Analytics