Java内部类

来源:互联网 发布:ctp交易接口源码 编辑:程序博客网 时间:2024/06/06 19:03

今天读到《Java核心技术》的内部类部分,感觉这一部分挺重要的,所以就在这里记录一下,供日后参考之用。
内部类(inner class)是定义在另一个类中的类。
先来列举一下,使用内部类的原因:
1.内部类方法可以访问该类定义所在的作用域中的数据,包括私有的数据。
2.内部类可以对同一个包中的其他类隐藏起来。
3.当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷。

在这里,列举一个例子:

public class TestActivity {    boolean b;    public class A{        private void a(){            if(b){                //do something            }        }    }    public static void main(String args[]) {     }}

在这里,A类内部是可以调用b的,也就是说,内部类可以可以访问自身的数据域,也可以访问创建他们外围类对象的数据域。

内部类的对象总有一个隐式引用,它指向了创建它的外部类的对象。而这个引用在内部类的定义中是不可见的。编译器修改了所有的内部类的构造器,添加一个外围类引用的参数。

下面是内部类的创建方式,同样通过外部类的对象去创建。

    TestActivity testActivity = new TestActivity();    TestActivity.A a = testActivity.new A();    a.a();

在这里我还要插一句,我们要注意这个问题:Android代码混淆导致内部类不可用。在进行Android开发的时候需要特别注意一下。

局部内部类

public class TestActivity {    boolean temp;    public class A{        private void a(){        }       }    public void a(){        class B{            public void inner(){                //todo            }        }        new B().inner();    }    public static void main(String args[]) {         TestActivity testActivity = new TestActivity();        TestActivity.A a = testActivity.new A();        a.a();    }}

看上面的代码,唯一跟之前不同的是在a方法内部定义了一个B类。B类就是局部内部类。编译器不允许使用public或者private进行声明。它的作用域被限定在声明这个局部类的块中。这样子的话,B类就可以对外部世界完全隐藏起来,即使TestActivity也无法访问它。

关于final变量和局部内部类

再看如下代码:

public class TestActivity {    boolean temp;    public class A{        private void a(){        }       }    public void a(){        final String s = "ddd";        class B{            public void inner(){                System.err.println(s);            }        }        new B().inner();    }    public static void main(String args[]) {         TestActivity testActivity = new TestActivity();        TestActivity.A a = testActivity.new A();        a.a();    }}

这里我们在a()方法里定义了一个String变量,然后在B类里引用这个对象,发现这个变量s必须是final的编译器才允许我们通过编译。也就是说,局部内部类只能访问外围方法里的final类型的变量。原因这篇文章写得挺好的:http://blog.csdn.net/salahg/article/details/7529091,谢谢作者~

匿名内部类

匿名内部类(Anonymous Inner Class),在创建实例的同时给出类的定义,所有这些在一个表达式中完成。我们经常在Android里使用匿名内部类。如下:

Runnable rn = new Runnable() {    public void run() {    }};

匿名内部类会隐式地继承一个父类或实现一个接口。匿名内部类要么继承一个父类,要么实现一个接口,不能两者兼有,不能同时实现多个接口。
可以参考http://www.cnblogs.com/nerxious/archive/2013/01/25/2876489.html 谢谢作者~

静态内部类

有的时候,使用内部类只是为了把一个类隐藏在另外一个类的内部,并不需要内部类引用外围类对象。为此,我们可以把内部类声明为static,以便避免它们之间的引用关系。
只有内部类可以被声明为static。静态内部类的对象除了没有生成它的外围类对象的引用特权外,与其他所有内部类完全一样。
我们在进行Android开发的时候,尽量使用静态内部类而不是普通内部类是因为静态内部类不持有外围类的引用,可以在一定程度上避免内存泄漏的问题。

上面是我的一些记录,以供自己查阅。

1 0