内部类

来源:互联网 发布:淘宝阿里妈妈是什么 编辑:程序博客网 时间:2024/05/17 02:18

基本概念

  • 内部类控制可视性,是一种代码隐藏机制,内部类了解外围类,并能与之通信。
  • 内部类对象的创建关联外围类的引用来创建,如果编译器访问不到此引用就会报错,内部类可以访问外围类的方法和字段。
  • 内部类引用外部类对象:外部类名.this。
  • 内部类可以访问外围类的所有资源,可以在内部类中返回外部类对象的引用,外部类名.this
    【在对象的构造过程中,this隐含在构造器中,使得对象和类关联。】
  • 内部类声明为static,那么内部类对象与外部类对象就没有关系,可以直接通过外部类.内部类创建。
  • 普通的内部类对象隐式的保存了一个指向它外围对象的引用,static的内部类对象则没有。所以,static内部类中就没有this这个引用。【有点类似于基类的static字段和方法是被导出类共享的】
  • 普通内部类不能有static数据和static 字段,static内部类可以有。

  1. 非静态内部类:通过外部类对象创建。外部类.内部类 obj=new 外部类对象.内部类()
  2. 静态内部类:直接通过外部类创建。 外部类.内部类=new 外部类.内部类()

  • private内部类给类的设计者提供类了一种途径,通过这种方式可以完全阻止任何依赖于类型的编码,并且完全隐藏实现的细节。
  • 内部类提供了某种进入其外围类的接口,内部类有权操作所有的成员,包括private。(内部类可以使用其外围类的资源)
  • 每个内部类都能独立的继承自一个接口的实现,所以无论外围类是否已经继承了某个接口的实现,对于内部类都是没有影响的。内部类使多重继承的方案变得完整,间接的实现了java的多重继承。

迭代器设计模式。

(迭代器作为内部类,要链接到外部类)

//迭代器接口interface Selector{ boolean end(); Object current(); void next();}public class Sequence{  private Objetc[] items;  private int next=0;  public Sequence(int size){    items=new Object[size];  }  public void add(Object x){    if(next<items.length){       items[next++]=x;    }  }  //迭代器作为内部私有类,可以访问外围类的所有属性。并且隐藏代码,封装  private class SequenceSelector implements Selector{    private int i=0;    public boolean end(){        return i==items.length;    }    public Object current(){       return items[i];    }    public void next(){      if(i<items.length)       i++;    }  }   //返回该内部类实例化对象  public Selector selector(){     return new SequenceSelector();  } }

调用:

Sequence sequence=new Sequence(10);for(int i=0;i<10;i++){  sequence.add(Integer.toString(i));}Selector selector=sequence.selector();//得到内部迭代器对象while(!selector.end()){  selector.next();}

内部类的分类

成员内部类和局部内部类

-成员内部类: 作为外围类成员使用
- 局部内部类:放在方法内部的

这里写图片描述

匿名内部类

new 接口/抽象类{   重写接口或抽象类的方法}

本质是继承该类或实现该接口的子类匿名对象。


  1. 类实例化创建对象,用传统方法创建还是匿名内部类创建对象,就看这个对象使用几次,匿名内部类只能使用一次就被释放掉了。
  2. 用局部内部类(有名称的类)还是匿名内部类创建对象的区别:匿名内部类和局部类都可以重写父类方法,不同的是局部内部类有名称,有名称就可以编写构造器,可以重写覆写等,而匿名内部类只能用来实例化对象。

内部类可以用来创建公共代码,可以用来被某个接口的所有不同实现所共用代码

java支持内部类多层嵌套

闭包与回调

内部类就是面向对象的闭包。
通过回调,对象能够携带一些信息。
比如,在内部类中,使用其外围类.this,作为“钩子”,回调到外围类。
回调的价值在于它的灵活性:可以在运行时动态的决定需要调用什么方法。(运行期通过钩子回调到外部类,并会携带一些信息)
在实现GUI的时候,到处都用到了回调。(比如,响应事件完成后,回调到Event)

内部类与控制框架(control framework)

应用程序框架(application framework)就是被设计用以解决某类特定问题的一个类或一组类。要运用某个应用程序框架,通常就是一个或多个类,并覆盖某些方法。应用程序框架提供的就是通用解决方案,即模板方法。设计模式总是将变化的事务与保持不变的事务分离开,在这个模式中,模板方法是保持不变的事务,可覆盖的方法就是变化的事务。
控制框架(control framework)是一类特殊的application framework,它用来解决响应事件的需求。主要用来响应事件的系统称作事件驱动系统。GUI中几乎全是事件驱动系统。比如,java Swing库就是一个控制框架。
内部类对事件驱动系统很重要,内部类用来表示响应一个类的各种不同事件的所必须的不同的action(每一种行为都作为类的一个内部类,都继承自Event,都有各自的实现方法。)
–更多内部类在application framework中的应用见《java编程思想中文第四版》p207

  1. 内部类使独立自主的,继承或者实现接口都是自己做主的,可以独立的响应不同的事件。
  2. 内部类可以自由的访问外围类的字段,无需限定条件或特殊许可。
  3. 内部类的构造器必须连接到指向其外围类对象的引用,所以一个类要直接继承自该内部类的话,会有点复杂,而且既然把类作为内部类嵌在外围类中,就是为了代码隐藏、代理、组合、回调和封装的,继承的话没有意义。–见《java编程思想中文第四版》p212
  4. 内部类定义在外围类的内部,不等于内部类是外围类的成员,内部类使完全独立的实体,会各自编译在自己的命名空间内。

内部类标识符

每个类都会产生一个.class文件,包含了如何创建该类型对象的全部信息,内部类也必须生成一个.class文件以包含它们的class对象信息。但是作为内部类,java的标准命名class文件的方式是:外围类$内部类。
如:LocalClass $ InnerClass.class
如果内部类是匿名的(new XXX{…重写XXX的方法…}),编译器会简单地产生一个数字作为其标识符。

0 0
原创粉丝点击