1.Scala_基础
package com.ecust.demo
/**
 * @author Jinxin Li
 * @create 2021-01-11 15:25
 */
object SparkCore05_Closure_Scala {
  //将函数作为返回值来使用
  def main(args: Array[String]): Unit = {
    def test() ={
      def inner()={
      }
      println("xxxxxx")
      //下划线表示将函数作为对象来使用
      val f = inner _
      f
    }
    //对上述方法调用
    val f: () => Unit = test()
    f()
    test()()
    def test1() ={
      def inner()={
      }
      //下划线表示将函数作为对象来使用
      inner _
    }
    //todo > 也可以直接指定类型 但是在企业中不这么用
    def test2():()=>Unit ={
      def inner()={
      }
      //下划线表示将函数作为对象来使用
      inner
    }
  }
  /*public User getUser(){
    User user = new User();
    return user;
  }*/
}
2.闭包
package com.ecust.demo
/**
 * @author Jinxin Li
 * @create 2021-01-11 15:34
 */
object SparkCore06_Closure_Scala {
  def main(args: Array[String]): Unit = {
    //1.outer函数=>方法
    //2.参数x编译后应该是方法的局部变量 局部变量有效范围是当前方法内部有效
    //3.inner函数=>文件中方法
    //4.inner方法执行时间点:在outer方法执行之后9
    //5.outer方法如果执行完了会弹出栈,其中的局部变量会回收
    //6.inner方法凭什么能用x 底层进行特殊操作,一个函数如果使用了外部的变量,需要将变量的生命周期改变
    //7.函数将变量包含到函数的内部,形成一个闭合的效果,称之为闭包
    //8.早期是使用匿名内部类实现的
    def outer(x:Int)={
      println("执行外部程序")
      def inner(y:Int)={
        println("执行内部程序")
        x+y
      }
      inner _
    }
    val f: Int => Int = outer(20)
    println(f)
    val i: Int = f(20)
    println(i)
//    println(outer(20)(20))
  }
}
3.Java模仿
package com.ecust.demo;
/**
 * @author Jinxin Li
 * @create 2021-01-11 15:49
 */
public class SparkCore08_Closure_Scala {
    private static int x = 10;
    public static void main(String[] args) {
        SparkCore08_Closure_Scala obj = new SparkCore08_Closure_Scala();
        //先执行方法outer,方法弹出栈
        int outer = obj.outer(20);
        //在执行方法inner
        int inner = obj.inner(20);
//        System.out.println(x);
        System.out.println(inner);
    }
    //java方法中不能写方法
    /*public void outer(int x){
        public void inner(){
        }
    }*/
    public int outer(int x){
        return x;
    }
    public int inner(int y){
        return x+y;
    }
}
4.实战1
package com.ecust.demo
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
/**
 * @author Jinxin Li
 * @create 2021-01-11 16:19
 */
object SparkCore09_Closure_Spark {
    def main(args: Array[String]): Unit = {
      val conf: SparkConf = new SparkConf().setAppName("SparkCoreTest").setMaster("local[*]")
      val sc: SparkContext = new SparkContext(conf)
      val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4))
      val user = new user()
      rdd.foreach(
        num=>{
          println("age:" + user.age+num)
        }
      )
      sc.stop()
    }
  //这里可以选择是否进行序列化类
  class user extends Serializable {
    var age:Int= 30
  }
}
5.实战2
package com.ecust.demo
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
/**
 * @author Jinxin Li
 * @create 2021-01-11 16:19
 * 这种情况下还是不能运行,因为需要进行闭包检查,当executor内部引用了外部变量时,就会监测外部变量能否使用
 */
object SparkCore10_Closure_Spark {
    def main(args: Array[String]): Unit = {
      val conf: SparkConf = new SparkConf().setAppName("SparkCoreTest").setMaster("local[*]")
      val sc: SparkContext = new SparkContext(conf)
      val rdd: RDD[Int] = sc.makeRDD(List[Int]())
      val user = new user()
      rdd.foreach(
        //todo 源码:ClosureCleaner.clean(f, checkSerializable)
        num=>{
          println("age:" + user.age+num)
        }
      )
      sc.stop()
    }
  //这里可以选择是否进行序列化类
  class user extends {
    var age:Int= 30
  }
}
6.总结
在spark的scala程序中,我们都是定义的main方法
main方法中又定了在executor的方法
executor在使用main方法中的变量时,要进行要将main方法变量提高生命周期,
版本之前以匿名内部类的方法实现,在调用之前检查能够进行序列化传输
并编译成高声明周期的变量
称为闭包检查