Lambda 表达式(5)

195 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第27天,点击查看活动详情

继续......Lambda 表达式,之前,整理了几次了,都没有涉及完全,今天继续,主要整理一下 Lambda 表达式的作用域......冲......

Lambda 表达式的作用域

Lambda 表达式可以看作是匿名内部类实例化的对象,Lambda 表达式对变量的访问限制和匿名内部类一样,因此 Lambda 表达式可以访问局部变量、局部引用、静态变量、实例变量。

访问局部变量

在 Lambda 表达式中,规定 只能引用标记了 final 的外层局部变量。不能在 Lambda 内部修改定义在域外的局部变量,否则会编译错误。

    public class TestFinalVariable {
    
        interface TestInterface {
            Integer change(String str);
        }
        
        public static void main(String[] args) {
            //局部变量未使用 final 修饰
            Integer testInt = 1;
            TestInterface testInterface = (str -> Integer.valueOf(str + testInt));
            //再次修改,不符合隐式 final 定义
            testInt = 2;
            Integer testStr = testInterface.change("cgx");
            System.out.println(testStr);
        }
    }

上述代码会出现编译报错,错误类似 Error:(XX, XX) java:从lambda表达式引用的本地变量必须是最终变量或实际上的最终变量

特殊情况,局部变量也可以不用 final 修饰,但是必须不可被后面的代码修改(即隐性的具有 final 的特性)

将上述代码改造,确保 Lambda 表达式后局部变量不做修改,就不会编译报错了:

        public class TestFinalVariable {
    
        interface TestInterface {
            Integer change(String str);
        }
        
        public static void main(String[] args) {
            //局部变量未使用 final 修饰
            Integer testInt = 1;
            TestInterface testInterface = (str -> Integer.valueOf(str + testInt));
            Integer testStr = testInterface.change("cgx");
            System.out.println(testStr);
        }
    }

访问局部变量、静态变量、实例变量

Lambda 表达式不限制访问局部引用变量、静态变量、实例变量:

    public class TestOtherVariable {

        //静态变量
        private static String staticVar;

        // 实例变量
        private static String instanceVar;

        @FunctionalInterface
        interface VarChangeInterface{
            Integer change(String str);
        }

        //测试引用变量
        private void  testReferenceVar(){
            ArrayList<String> list = new ArrayList<>();
            list.add("111");
            //访问外部引用局部引用变量
            VarChangeInterface varChangeInterface = ((str) -> Integer.valueOf(list.get(0)));
            //修改局部引用变量
            list.set(0,"222");
            Integer str =varChangeInterface.change("");
            System.out.println(str);
        }


        //测试静态变量
        void testStaticVar(){
            staticVar="222";
            VarChangeInterface varChangeInterface = (str -> Integer.valueOf(str+staticVar));
            staticVar="333";
            Integer str =varChangeInterface.change("111") ;
            System.out.println(str);
        }

        //测试实例变量
        void testInstanceVar(){
            instanceVar="222";
            VarChangeInterface varChangeInterface = (str -> Integer.valueOf(str+instanceVar));
            instanceVar="333";
            Integer str =varChangeInterface.change("111") ;
            System.out.println(str);
        }

        public static void main(String[] args) {
            new TestOtherVariable().testReferenceVar();
            new TestOtherVariable().testStaticVar();
            new TestOtherVariable().testInstanceVar();
        }
    }

结果:
    222
    111333
    111333

注意:Lambda 表达式中不允许声明一个与局部变量同名的参数或局部变量:

    Integer testInt = 1;
    VarTestInterface varTest1 = (testInt -> Integer.valueOf(testInt));
    VarTestInterface varTest2 = (str -> {
        Integer testInt = 1;
        Integer.valueOf(str);
    });

上述代码中 testInt 声明时重名,会编译报错!

每天稍微整理一点,太多了也怕消化不了[doge],明天继续......
希望本文能够帮到你,如有错误,望指正!
我向你敬礼啊,Salute!