内部类
内部类可以分为4种:成员内部类、局部内部类、匿名内部类和静态内部类。
1.成员内部类
当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即默认情况下访问的是成员内部类的成员。
如果要访问外部类的同名成员,需要以下面的形式进行访问:
外部类.this.成员变量
外部类.this.成员方法
2.局部内部类
3.匿名内部类
匿名内部类是唯一一种没有构造器的类。正因为其没有构造器,所以匿名内部类的使用范围非常有限,大部分匿名内部类用于接口回调。 匿名内部类在编译的时候由系统自动起名为Outter$1.class。
4.静态内部类
静态内部类是不需要依赖于外部类的,不持有指向外部类对象的引用。
它和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法。
5.原理分析:
①内部类如何访问外部类?
编译器会默认为成员内部类添加了一个指向外部类对象的引用。
虽然我们在定义的内部类的构造器是无参构造器,编译器还是会默认添加一个参数,该参数的类型为指向外部类对象的一个引用,
所以成员内部类中的Outter this&0 指针便指向了外部类对象,因此可以在成员内部类中随意访问外部类的成员。
②为什么局部内部类和匿名内部类只能访问局部final变量?
编译器会对局部变量进行特别处理:
如果局部变量的值在编译期间就可以确定,则直接在匿名内部里面创建一个拷贝。
如果局部变量的值无法在编译期间确定,则通过构造器传参的方式来对拷贝进行初始化赋值。
这样的话,如果外部类修改局部变量的值、会造成数据不一致性、所以需要使用final来保证数据一致。
③为什么非静态内部类不能有静态成员变量和静态方法?
static类型的属性和方法,在类加载的时候就会存在于内存中。
要想是用某个类的static属性和方法,那么这个类必须要加载到虚拟机-中。
非静态内部类并不随外部类一起加载,只有在实例化外部类之后才会加载。
为了避免外部类并没有实例化,内部类还没有加载,这时调用内部类的静态成员或方法的矛盾。所以非静态内部类不能有静态成员变量或静态方法。
④内部类的private属性与父类的private属性互相可见 为什么?
Java语言规范里只说了enclosing class可以访问inner class的private/protected成员,inner class也可以访问enclosing class的private/protected成员。
具体实现与编译器有关
简单来说就是在enclosing / inner class之间要访问对方的private/protected成员时,javac会生成合适的“access method”(上面的access$xxx形式的方法)来提供合适的可访问性,这样就绕开了原本的成员的可访问性不足的问题。
public class Outer {
private int outProp = 8;
class Inner {
private int inProp = 5;
}
public void accessInnerProp() {
System.out.println(new Inner().inProp);
}
public static void main(String[] args) {
Outer p = new Outer();
p.accessInnerProp();
}
}
编译为:
public class Outer {
private int outProp;
public Outer() {
super();
this.outProp = 8;
}
public void accessInnerProp() {
System.out.println(Outer$Inner.access$000(new Outer$Inner(this)));
}
public static void main(String[] args) {
Outer p = new Outer();
p.accessInnerProp();
}
}
class Outer$Inner {
private int inProp;
final /* synthetic */ Outer this$0;
Outer$Inner(Outer outer) {
this.this$0 = outer;
super();
this.inProp = 5;
}
static /* synthetic */ int access$000(Outer$Inner self) {
return self.inProp;
}
}
6.内部类的使用场景和好处
为什么在Java中需要内部类?总结一下主要有以下四点:
①每个内部类都能独立的继承一个接口的实现,所以无论外部类是否已经继承了某个(接口的)实现,对于内部类都没有影响。内部类使得多继承的解决方案变得完整。
②方便将存在一定逻辑关系的类组织在一起,又可以对外界隐藏。
③方便编写事件驱动程序
④方便编写线程代码
http://www.cnblogs.com/dolphin0520/p/3811445.html
//成员内部类
//private属性与父类的private属性互相可见
//相当于父类的成员变量 因此父类的静态变量或方法不能调用成员内部类
//成员内部类本身不能含有静态变量 静态方法
//静态内部类
//private属性与父类的private属性互相可见 成员变量除外
//相当于父类的静态变量 因此不能调用父类的成员变量