Java内部类详解

内部类的共性


内部类分为: 成员内部类、静态嵌套类、方法内部类、匿名内部类。
(1)、内部类仍然是一个独立的类,在编译之后内部类会被编译成独立的.class文件,但是前面冠以外部类的类名和$符号。
(2)、内部类不能用普通的方式访问。内部类是外部类的一个成员,因此内部类可以自由地访问外部类的成员变量,无论是否是private的。

(3)、内部类声明成静态的,就不能随便的访问外部类的成员变量,仍然是只能访问外部类的静态成员变量。


static对类的修饰来说,是不能修饰普通类的,只能修饰内部类。


1、成员内部类


class Outer {
class Inner{}
}
编译上述代码会产生两个文件:Outer.class和Outer$Inner.class。


成员内部类里不能定义static变量和方法,但是可以使用外部类里的static及普通成员变量和方法。


2、方法内部类


这种内部类比较特殊,如果你试图在方法内部类前面加上修饰符,都会报错,eclipse会提示你只能为abstract或final。意思就是这种内部类的访问权限是定好的,而且不能为static。


(1)、方法内部类只能在定义该内部类的方法内实例化,不可以在此方法外对其实例化,而且对方法外不可见


(2)、方法内部类对象不能使用该内部类所在方法的非final局部变量。


(3)、方法内部类可以访问并使用外部类的成员变量或者静态变量,成员方法和静态方法。


(4)、方法内部类不能定义静态变量和方法。


方法内部类编译后会生成一个Outer$1Inner.class,注意,内部类名前面会加一个数字,如果其他方法里有同样名字的内部类,会按照编号继续Outer$2Inner.class、Outer$1Inner.class等。


因为方法的局部变量位于栈上,只存在于该方法的生命期内。当一个方法结束,其栈结构被删除,局部变量成为历史。但是该方法结束之后,在方法内创建的内部类对象可能仍然存在于堆中!例如,如果对它的引用被传递到其他某些代码,并存储在一个成员变量内。正因为不能保证局部变量的存活期和方法内部类对象的一样长,所以内部类对象不能使用它们。


3、匿名内部类


顾名思义,没有名字的内部类。最常见的就是new一个Ruunable了。一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。


以下情况使用匿名内部类是比较合适的:
·只用到类的一个实例。
·类在定义后马上用到。
·类非常小(SUN推荐是在4行代码以下),而且可能只需要重写里面的少量方法。


内部类其实有点和变量差不多,个人认为可以当作一个变量来使用,如果和外部类的成员变量写在一起,其实就是一个变量了。

写在方法里,也就是个临时变量。但是但是,有一点,和外部类的变量写在一起,那就是个变量,不会编译成class文件;但是写在方法内部的匿名内部类,会编译成class文件,编译成Outer$1.class、Outer$2.class,尼玛连名字都没有,就是这样,所以我觉得这应该是叫做匿名内部类的原因。


匿名内部类也分三种:

1、继承式内部类,经常用到的new一个Thread就是这种喽

2、接口式,Runnable就是这种

3、参数式匿名内部类:如下,就是当作函数参数

class Bar{
void doStuff(Foo f){}
}
interface Foo{
void foo();
}
class Test{
static void go(){
Bar b = new Bar();
b.doStuff(new Foo(){
public void foo(){
System.out.println("foofy");
}
});
}
}


这三种都会被编译成那种连名字都没有的class文件。


方法内的匿名内部类的一些原则和方法内部类有些相似:

(1)、不能使用该内部类所在方法的非final局部变量。


(2)、可以直接访问并使用外部类的成员变量或者静态变量,成员方法和静态方法。


(3)、类里不能定义静态变量和方法。


(4)、不能有构造方法


4、静态嵌套类


和成员内部类很像,编译出来的class文件形式也一样,就是多了一个static修饰符,既然分类出来了,就说一说吧。


成员内部类里不能定义static变量和方法,但是静态嵌套类里可以有。但是静态嵌套类仅能访问外部类的静态成员和方法。


从技术上讲,静态嵌套类不属于内部类。因为内部类与外部类共享一种特殊关系,更确切地说是对实例的共享关系。而静态嵌套类则没有上述关系。它只是位置在另一个类的内部,因此也被称为顶级嵌套类。


静态的含义是该内部类可以像其他静态成员一样,没有外部类对象时,也能够访问它。


5、还有一种内部类是定义在一个类文件的主类外的,其实也不算严格意义上的内部类。


我们知道在Java里,一个类文件只能有一个主类;在主类外定义的内部类,这种内部类和方法内部类相似,也是不能用除了abstract和final之外的修饰符。意思就是默认包访问,而且不能自由使用主类的变量了,因为写在外面就默认是两个不相干的类了,只是在一个文件里而已。


这种类不论用abstract还是final修饰,都会编译生成一个Inner.class,前面没有外部主类的前缀。


—————————————————MB终于写完了,累死了————————————————————

本文理论部分参考百度百科:http://baike.baidu.com/view/7942850.htm,不过我都亲自用代码验证过无误。


你可能感兴趣的:(Java)