java 閉包與回調


  閉包是一塊代碼可以傳入另外一個地方,並且在終點處可以運行該代碼。用編程語言來描述,就是指可以把一個函數(類對象)打包傳入另一個函數(類對象)里,通常指客戶端調用處。java閉包主要是通過接口+內部類來實現,有兩種形式:接口+內部類和接口+局部內部類

  一、接口+內部類

  class Outer {

    private class Inner implements Runable {

      @Overide

      public void run() {

        System.out.println("Outer.Inner.run");

      }

    }

    

    public Runable getRun() {

      return new Inner();

    }

  }

  把內部類Inner聲明為private,使外界無法訪問,getRun方法返回一個內部類的實例。在客戶端調用:

Runable run = new Outer().getRun();

run.run(); // 客戶端得到Inner實例,並可調用run方法,這就是延遲運行,並inner實例傳到外界客戶端里

 

  二、接口+局部內部類:  

  class Outer {    

    public Runable getRun() {

      class Inner implements Runable {

        @Overide

        public void run() {

          System.out.println("Outer.getRun.Inner.run");

        }

      }

      return new Inner();

    }

  }

  

  這兩種方式都可實現閉包,而在客戶端調用內部類的過程,稱為回調。

 

  下面列出與JS閉包的不同之處:

  java:

  class Outer {

    public List<Runable> getRunList() {

      List<Runable> list = new ArrayList(10);

      for (int i = 0; i < 10; i++) {
        int temp = i;

        list.add(new Runable() {

          @Override

          public void run() {

            System.out.print(temp + " ");

          }

        });
      }

      return list;

    }

  }

  調用:

  List<Runable> list = new Outer().getRunList();

  for (Runable item : list) {

    item.run();

  }

  // 循環輸出:0 1 2 3 4 5 6 7 8 9

 

  javascript:

  function Outer {

    var tempList = [];

    for (var i = 0; i < 10; i++) {

      tempList[i] = function () {

        return i;

      }

    }

    return tempList;

  }

  調用方:

  var list = Outer();

  for (var i = 0; i < list.length; i++) {

    Console.write(list[i]() + " "); // 閉包回調

  }

  // 輸出結果:10 10 10 10 10 10 10 10 10 10 

 

  由上可以看出,同樣的代碼邏輯,java和js執行結果不一樣。這是因為js變量作用域在for, if 和  { }塊時,它的作用域都超出塊體外,在閉包調用時,會取出最后一個值為10。而java作用不同,隨着塊級}結束而結束,所以調用時,都取的是i的副本(已經將對應值存入)。另外C#的委托也是實現閉包的一種。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM