java-内部类

内部类

内部类可以分为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属性互相可见  成员变量除外
//相当于父类的静态变量 因此不能调用父类的成员变量

转载于:https://my.oschina.net/dajianguo/blog/857048

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值