《Java编程思想》之为什么需要内部类?

上接Java编程思想》之内部类——深奥而复杂

13、为什么需要内部类?

1).内部类最吸引人注意的原因是:每个内部类都能独立的继承自一个(接口的)实现,所以无论外围类是否已经继承了某个就(接口的)实现,对于内部类都没有影响。

2).一个类中以某种方式实现两个接口。由于接口的灵活性,你有两种选择:使用单一类,或者使用内部类。从实现观点看,以下俩种方式没什么区别。

interface A{}
interface B{}
 
class X implements A, B{}
 
class Y implements A{
   B makeB(){
      return new B(){
        
      };
   }
}
 
public class MultiInterfaces{
   static void takesA(A a){}
   static void takesB(B b){}
   public static void main(String[] args){
      X x = new X();
      Y y = new Y();
      takesA(x);
      takesA(y);
      takesB(x);
      takesB(y.makeB());
   }
}

3).如果拥有的是抽象类或具体的类,而不是接口,那就只能使用内部类才能实现多重继承。

4).内部类还可以获得其他一些特性(不是很理解!!):

·内部类可以有多个实例,每个实例都有自己的状态信息,并且与外围类对象的信息相互独立。

·在单个的外围类中,可以让多个内部类以不用的方式实现同一接口,或继承同一个类。

·创建内部类对象的时刻并不依赖外围类对象的创建。

·内部类并没有令人迷惑的“is-a”关系;它就是一个独立的实体。

请看下面例子:

interface Selector{
   boolean end();
   Object current();
   void next();
}
public class Sequence{
   private Object[] objects;
   private int next = 0;
   public Sequence(int size){
      objects = new Object[size];
   }
   public void add(Object x){
      if(next < objects.length)
        objects[next++] = x;
   }
   private class SSelector implements Selector{
      private int  i = 0;
      public boolean end(){
        return i == objects.length;
      }
      public Object current(){
        return objects[i];
      }
      public void next(){
        if(i < objects.length)
           i++;
      }
   }
   public Selector getSelector(){
      return new SSelector();
   }
   public static void main(String[] args){
      Sequence sequence = new Sequence(10);
      for(int i = 0; i < 10; i++)
        sequence.add(Integer.toString(i));
      Selector selector = sequence.getSelector();
      while(!selector.end()){
        System.out.println(selector.current());
        selector.next();
      }
   }
}

如果Sequence不适用内部类,就必须声明“Sequence是一个Selector”,对于某个特定的Sequence只能又一个Selector。同时,使用内部类很容易就能拥有另一个方法getRSelector(),用它来生成一个反方向遍历的Selector。只有内部类才有这种灵活性

14、闭包是一个可调用的对象,它记录了一些信息,这些信息来自于创建它的作用域。内部类是面向对象的闭包。因为它不仅包含外围类对象(“创建内部类的作用域”)的信息,还自动拥有一个指向此外围对象的引用,在此作用域内,内部类操作所有成员,包括“private”成员。

15、Java最具有争议的问题之一就是,人们认为Java应该包含某种类似指针的机制,以允许回调。通过回调,对象能够携带一些信息,这些信息允许它在稍后的某个时刻调用初始的对象。

通过内部类提供闭包的功能是完美的解决方案,它比指针更灵活、更安全。见下例:

interface Incrementable{
   void increment();
}
//外部类实现接口
class Callee1 implements Incrementable{
   private int  i = 0;
   public void increment(){
      i++;
      System.out.println(i);
   }
}
class MyIncrement{
   void increment(){
      System.out.println("MyIncrement.increment()");
   }
   static void func(MyIncrement myIncrement){
      myIncrement.increment();
   }
  
}
 
class Callee2 extends MyIncrement{
   private int i = 0;
   private void incr(){
      i++;
      System.out.println(i);
   }
   //内部类实现接口
   public class Closureimplements Incrementable{
      public void increment(){
        incr();
      }
   }
   Incrementable getCallBackReference(){
      return new Closure();//向上转型
   }
}
class Caller{
   private Incrementable callBackReference;
   Caller(Incrementable callBackReference){
      this.callBackReference = callBackReference;
   }
   void go(){
      callBackReference.increment();
   }
}
public class Callbacks{
   public static void main(String[] args){
      Callee1 c1 = new Callee1();
      Callee2 c2 = new Callee2();
      MyIncrement.func(c2);
      Caller caller1 = new Caller(c1);
      Caller caller2 = new Caller(c2.getCallBackReference());
      caller1.go();
      caller1.go();
      caller2.go();
      caller2.go();
     
   }
}

   Callee2继承自MyIncrement,有一个与Incrementable接口相同名字的increment()方法,但是两者的Increment()方法行为不同。所以如果Callee2继承了MyIncrement,就不能为了Incrementable的用途而覆盖increment()方法,于是只能使用内部类独立的实现Incrementable。还要注意,当创建了一个内部类时,并没有在外围类的接口中添加东西,也没有修改外围类的接口。

   Callee2中内部类Closure 里的getCallBackReference()方法,返回一个Incrementable的引用,无论谁获得此引用,都只能调用increment(),除此之外没有其他功能(不像指针那样,允许你做很多事情)。

       回调的价值在于它的灵活性——可以在运行时动态决定需要调用什么方法。

16、

1). 应用程序框架(applicationframeword)就是被设计用来解决某类特定问题的一个类或一组类。

2).要运行某个应用程序框架,通常是继承一个或多个类,并覆盖某个方法。

3).控制框架是一类特殊的应用程序框架,它用来解决响应事件的需求。

4).主要用来响应事件的系统被称作事件驱动系统

点击请看一例子,能更好了解内部类的价值。

以上内容整理自《Java编程思想》,若有遗漏,请您不吝指出!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值