精华内容
下载资源
问答
  • Lambda 表达式中, 访问外层作用域和以前版本的匿名对象中的方式类似。 可以直接访问标记了 final 的外层局部变量、 对象的字段与静态变量。 访问局部变量 在 Lambda 表达式中, 直接访问外层的局部变量。 与...

    在 Lambda 表达式中, 访问外层作用域和以前版本的匿名对象中的方式类似。 可以直接访问标记了 final
    的外层局部变量、 对象的字段与静态变量。

    1. 访问局部变量
      在 Lambda 表达式中, 直接访问外层的局部变量。
      与匿名对象不同的是, 变量 number 可以不声明为 final。
      代码如下:
    package test;
    
    public class Lambda {
    
    	public static void main(String[] args) {
    		int number = 6;
    		InterNew<Integer,String>inn = (t) -> String.valueOf(t + number);
    		System.out.println("访问局部变量:"+inn.InterNew(7));
    	}
    
    }
    interface InterNew<String, Integer> {
    	Integer InterNew(String string);
    }
    
    

    运行结果:
    访问局部变量:13

    1. 访问对象字段与静态变量
      在 Lambda 表达式中修改变量 number 同样是不允许的。 与本地变量不同, Lambda 表达式内部对于对
      象的字段以及静态变量是即可读又可写, 这与匿名对象是相同的。
      访问对象字段与静态变量。
    package test;
    
    public class Lambda {
    
    		public static int sNum;
    		public int num;
    
    		public void varTest() {
    			InterNew<Integer, String> is = (t) -> {
    				num = 56; // 成员变量
    				return String.valueOf(t);
    			};
    			System.out.println(is);
    			InterNew<Integer, String> is2 = (t) -> {
    				sNum = 98; // 静态变量
    				return String.valueOf(t);
    			};
    			System.out.println(is2);
    		}
    
    		public static void main(String[] args) {
    			Lambda l = new Lambda();
    			l.varTest();
    		}
    }
    
    

    运行结果:
    test.LambdaKaTeX parse error: Can't use function '$' in math mode at position 7: Lambda$̲1/791452441@1c2…Lambda$2/531885035@816f27d

    展开全文
  • 主要介绍了Java中Lambda表达式之Lambda语法与作用域解析重点介绍Lambda表达式基础知识,需要的朋友可以参考下
  • Lambda 表达式的作用域 1.访问局部变量 2.访问对象字段与静态变量 3.不能访问接口的默认方法 4.Lambda表达式中的this 5.综合理解Lambda表达式的作用域 …………


    Lambda 表达式的作用域


    文 | 莫若吻     


    Lambda表达式中访问外层作用域和旧版本的匿名对象中的方式类似。你可以直接访问标记了final的外层局部变量,或者实例的字段以及静态变量。

    Lambda表达式不会从超类(supertype)中继承任何变量名,也不会引入一个新的作用域。Lambda表达式基于词法作用域,也就是说lambda表达式函数体里面的变量和它外部环境的变量具有相同的语义(也包括lambda表达式的形式参数)。此外,this关键字及其引用,在Lambda表达式内部和外部也拥有相同的语义。


    Lambda表达式全文地址:http://blog.csdn.net/sun_promise/article/details/51121205

    1.访问局部变量

    1)可以直接在lambda表达式中访问外层的局部变量

    eg:

    final int num = 1;
    Converter<Integer, String> s =
            (param) -> String.valueOf(param + num);
     
    s.convert(2);     // 3

    但是和匿名对象不同的是,lambda表达式的局部变量(eg:num)可以不用声明为final

    eg:

    int num = 1;
    Converter<Integer, String> s =
            (param) -> String.valueOf(param + num);
     
    stringConverter.convert(2);     // 3

    不过这里的局部变量(eg:num)必须不可被后面的代码修改(即隐性的具有final的语义)

    eg:下面代码无法编译

    int num = 1;
    Converter<Integer, String> s =
            (param) -> String.valueOf(param + num);
    num = 5;

    Note:在Lambda表达式中试图修改局部变量是不允许的。


    2)在 Lambda 表达式当中被引用的变量的值不可以被更改。

    public void repeat(String string, int count) {
            Runnable runnable = () -> {
                for (int i = 0; i < count; i++) {
                    string = string + "a";//编译出错
                    System.out.println(this.toString());
                }
            };
            new Thread(runnable).start();
    }

    3)在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。

    eg:

    String first = "";
    Comparator<String> comparator = (first, second) -> Integer.compare(first.length(),//编译会出错
                    second.length());


    2.访问对象字段与静态变量

    和局部变量不同的是,Lambda内部对于实例的字段(即:成员变量)以及静态变量是即可读又可写。

    eg:

    class LambdaDemo {
        static int myStaticNum;
        int myNum;
     
        void testScopes() {
            Converter<Integer, String> s1 = (param) -> {
                myNum = 33;
                return String.valueOf(param);
            };
     
            Converter<Integer, String> s2 = (param) -> {
                myStaticNum = 87;
                return String.valueOf(param);
            };
        }
    }


    3.不能访问接口的默认方法

    Lambda表达式中是无法访问到默认方法的。


    4.Lambda表达式中的this

    Lambda 表达式中使用 this 会引用创建该 Lambda 表达式的方法的 this 参数。

    eg:

    public class Test2 {
        public static void main(String[] args) {
            Test2 test = new Test2();
            test.method();
        }
        @Override
        public String toString() {
            return "Lambda";
        }
        public void method() {
            Runnable runnable = () -> {
                System.out.println(this.toString());
            };
            new Thread(runnable).start();
        }
    }

    显示结果:Lambda


    5.综合理解Lambda表达式的作用域

    (注:如果上面的3条内容都理解了,就不用再仔细看下面这个示例和分析了。)

    eg:

    public class Test {
        public static void main(String[] args) {
            repeatMessage("Hello world", 20);
        }
        public static void repeatMessage(String text,int count){
            Runnable r = () -> {
                for(int i = 0; i < count; i++){
                    System.out.println(text);
                    Thread.yield();
                }
            };
            new Thread(r).start();
        }
    }
    分析: Lambda表达式中的变量count和text,它们并没有在Lambda表达式中被定义,而是方法的参数。Lambda表达式可能会在repeatMessage()返回之后才运行,此时参数变量已经消失了。如果保留text和count变量会怎样呢?

    为了更好地理解上面的情况,我们需要对Lambda表达式有更深入的理解。

    一个lambda表达式包括三个部分:

    • 一段代码。
    • 参数。
    • 自由变量的值,这里的“自由”指的是那些不是参数并且没有在代码中定义的变量。
    在示例中,lambda表达式有两个自由变量,text和count。数据结构表示Lambda表达式必须存储这两个变量的值,即“Hello world ”和20。可以理解为,这些值已经被Lambda表达式捕获了(这是一个技术实现的细节。eg:你可以将一个lambda表达式转换为一个只含一个方法的对象,这样自由变量的值就会被复制到该对象的实例变量中)。

    Note:含有自由变量的代码块才被称之为“闭包(closure)”。在Java中,lambda表达式就是闭包。事实上,内部类一直都是闭包。Java8中为闭包赋予了更吸引人的语法。


    Lambda表达式可以捕获闭合作用域中的变量值。在java中,为了确保被捕获的值是被良好定义的,需要遵守一个重要的约束。在Lambda表达式中,被引用的变量的值不可以被更改。

    eg:下面这个表达式是不合法的

    public static void repeatMessage(String text,int count){
        Runnable r = () -> {
            while(count > 0){
                count--;        //错误,不能更改已捕获变量的值
                System.out.println(text);
                Thread.yield();
             }
         };
         new Thread(r).start();
    }

    做出这个约束是有原因的。更改lambda表达式中的变量不是线程安全的。假设有一系列并发的任务,每个线程都会更新一个共享的计数器。

    int matches = 0;
    for(Path p : files)
    new Thread(() -> {if(p中包含某些属性) matches++;}).start();    //非法更改matches的值

    不要指望编译器会捕获所有并发访问错误。不可变的约束只作用在局部变量上,如果matches是一个实例变量或者闭合类的静态变量,那么不会有任何错误被报告出来即使结果同样未定义。同样,改变一个共享对象也是完全合法的,即使这样并不恰当。

    List<Path> matches = new ArrayList<>();
    for(Path p: files)
    //你可以改变matches的值,但是在多线程下是不安全的
    new Thread(() -> {if(p中包含某些属性) matches.add(p);}).start();

    Note:matches是“有效final”的(一个有效的final变量被初始化后,就永远不会再被赋一个新值的变量)。在我们的示例中,matches总是引用同一个ArrayList对象,但是,这个对象是可变的,因此是线程不安全的 。如果多个线程同时调用add方法,结果将无法预测。

    Lambda表达式的方法体与嵌套代码块有着相同的作用域。因此它也适用同样的命名冲突和屏蔽规则。在Lambda表达式中不允许声明一个与局部变量同名的参数或者局部变量。

    Path first = Paths.get("/usr/bin");
    Comparator<String> comp = (first,second) ->
        Integer.compare(first.length(),second.length());
    //错误,变量first已经定义了
    在一个方法里,你不能有两个同名的局部变量,因此,你也不能在lambda表达式中引入这样的变量。


    当你在Lambda表达式中使用this关键字,你会引用创建该Lambda表达式的方法的this参数,

    eg:

    public class Application{
        public void doWork(){
            Runnable runner = () -> {....;System.out.println(this.toString());......};
        }
    }

    表达式this.toString()会调用Application对象的toString()方法,而不是Runnable实例的toString()方法。在Lambda表达式中使用this,与在其他地方使用this没有什么不同。Lambda表达式的作用域被嵌套在doWork()方法中,并且无论this位于方法的何处,其意义都是一样的。



    展开全文
  • 这里是一个E的作用域lambda也有一个内部的作用域,在外层test函数的嵌套作用域内, 列表中加入的都是lambda函数的地址,并没与调用这个函数,因为嵌套作用域中的变量在嵌套的函数被调用时才进行查找,所以他们...

    命名空间的定义

    命名空间指的是保存程序中的变量名和值的地方。
    命名空间的本质是一个字典, 用来记录变量名称和值。
    字典的 key 是变量的名称,字典的 value 对于的是变量 的值。 例如 {‘name’:’zs’,’age’:10}
    命名空间一共分为三种:局部命名空间、全局命名空间、内置命名空间
    1,局部空间: 每个函数都有自己的命名空间,叫做局部空间,它记录了函数的变量,包括函数 的参数 和局部定义的变量
    2,全局空间: 每个模块拥有它自已的命名空间,叫做全局命名空间,它记录了模块的变量,包 括函数、 类、其它导入的模块。
    3,内置名称空间: 任何模块均可访问它,它存放着内置的函数和异常。

    命名空间的访问:

    1,局部名称空间使用 locals() 函数来访问
    2,全局命名空间的访问使用 globals()函数访问
    (print这两货就行了)

    命名空间加载顺序

    内置命名空间(程序运行前加载)->
    全局命名空间(当程序运行的时候加载全局命 名空间)->
    局部命名空间(程序运行中:函数被调用时才加载)

    命名空间查找顺序

    局部命名空间中找,如果能找到则停止搜索
    如果找不到
    全局命名空间中查找,如果找到则停止搜索
    如果找不到
    内置命名空间中查找,如果找不到则报错。

    嵌套函数的情况:
    1、先在当前 (嵌套的或 lambda) 函数的命名空间中搜索
    2、然后是在父函数的命名空间中搜索
    3、接着是模块命名空间中搜索
    4、最后在内置命名空间中搜索
    在这里插入图片描述

    作用域的定义

    作用域指的是变量在程序中的可应用范围。 作用域按照变量的定义位置可以划分为 4 类即 LEGB:
    1, Local(函数内部)局部作用域。
    2, Enclosing(嵌套函数的外层函数内部)嵌套作用域(闭包)。
    3, Global(模块全局)全局作用域。
    4,Built-in(内建)内建作用域。(指的是 builtins.py 模块)

    在这里插入图片描述
    内层作用域可以访问外层作用域,然外层作用域不能访问内层作用域,切记切记

    在 python 中,模块(module),类(class)、函数(def、lambda)会产生新的 作用域,其他代码块是不会产生作用域的,
    也就是说,类似条件判断(if……else)、 循环语句(for x in data)、异常捕捉(try…catch)等的变量是可以全局使用的。

    全局变量和局部变量

    在函数中定义的变量称为局部变量,只在函数内部生效,
    在程序一开始定义的变量称为全局变量,全局变量的作用域是整个程序。
    全局变量是不可变数据类型,函数无法修改全局变量的值
    全局变量是可变数据类型,函数可以修改全局变量的值
    当然,你可以使用global 和 nonlocal 关键字改变这一点,具体可以看我的博客其他文章:python基础知识回顾

    嵌套作用域和 lambda

    lambda 表达式也会产生一个新的局部作用域。
    在 def 定义的函数中嵌套 labmbda 表达式,lambda 表达式能够看到所有 def 定义的函数中可用的变量。
    给一个经典面试题:

    def test():
        l1 = []
        for i in range(5):
            l1.append(lambda n:i**n)
        return l1
    
    t = test()
    print(t[0](2))
    print(t[1](2))
    print(t[2](2))
    print(t[3](2))
    print(t[4](2))
    

    请给出打印的结果

    16
    16
    16
    16
    16
    

    5个16,知道为什么吗?我做一点小改动

    def test():
        l1 = []
        for i in range(5):
            l1.append(lambda n,i=i:i**n)
        return l1
    
    t = test()
    print(t[0](2))
    print(t[1](2))
    print(t[2](2))
    print(t[3](2))
    print(t[4](2))
    

    结果

    0
    1
    4
    9
    16
    

    现在想通了吗?
    这里是一个E的作用域,lambda也有一个内部的作用域,在外层test函数的嵌套作用域内,
    列表中加入的都是lambda函数的地址,并没与调用这个函数,因为嵌套作用域中的变量在嵌套的函数被调用时才进行查找,所以他们实际上记住的是同样的值(在最后一次循环选代中循环变量的值)。也就 是说,我们将从列表中的每个函数得到 4 的平方的函数。
    那么后面的改动做了些什么事情呢?匿名函数将嵌套作用域中的 “ i ”的变量赋予给了自己内部的“ i ”的变量,记忆了下来,列表在添加lambda对象的时候,也保存了其“ i ”值,所以最后调用的时候就能得到我们预期的结果了!!!

    展开全文
  • lambda表达式的变量作用域问题1、合法引用外部变量2、非法引用外部变量(lambda改变)3、非法引用外部变量(外部改变)4、5、lambda中使用this关键字 1、合法引用外部变量 import javax.swing.*; import java.awt....

    1、合法引用外部变量

    import javax.swing.*;
    import java.awt.event.ActionListener;
    
    public class App {
        public static void repeatMessage(String text, int delay) {
            ActionListener listener = event -> {
                System.out.println(text);
            };
            new Timer(delay, listener).start();
        }
        public static void main(String[] args) {
            /**
             * 代码运行现象,在repeatMessage函数返回后,任然可以输出"tangxin",
             * 这是为什么呢?
             * 因为text对于lambda表达式来说是自由变量,lambda表达式存在自由变量时,
             * 则lambda表达式将捕获这个值,左右在函数退出后,监听器任然可以打印这个值
             */
            App.repeatMessage("tangxin", 1000);
            System.out.println("repeatMessage返回");
            while(true);
        }
    }
    

    2、非法引用外部变量(lambda改变)

    当试图改变外部变量传递给text的值时,将会报错
    

    在这里插入图片描述

    3、非法引用外部变量(外部改变)

    当引用的外部变量可能会被重新赋值时,也是非法的。
    

    在这里插入图片描述

    4、lambda表达式中不可出现同名局部变量

    在lambda表达式中不可有同名的局部变量
    

    在这里插入图片描述

    5、lambda中使用this关键字

    import javax.swing.*;
    import java.awt.event.ActionListener;
    
    public class App {
        public void repeatMessage(String text, int delay) {
            ActionListener listener = event -> {
                System.out.println(text);
                /**
                 * 在一个lambda表达式中使用this关键字时,
                 * 是指创建这个lambda表达式的方法的this参数
                 * 也就是App的对象
                 */
                System.out.println(this.toString());
            };
            new Timer(delay, listener).start();
        }
        public static void main(String[] args) {
            App text = new App();
            text.repeatMessage("tangxin", 1000);
            while(true);
        }
    }
    
    展开全文
  • 通常,我们希望能够在lambda表达式的闭合方法或类中访问其他的变量,例如: package java8test; public class T1 { public static void main(String[] args) { repeatMessage("Hello", 20); } public sta...
  • lambda的变量作用域

    2019-12-13 11:19:52
    lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。 final static String salutation = "hello "; public static void main(String[] ...
  • 1)lambda表达式等价于一个小函数,表达式的值就是函数的返回值。 2)可以给lambda表达式起名字,也可以不起名字。 3)在lambda表达式中使用没有定义的变量,默认是全局变量。   这里就进行演示一下为什么lambda...
  • lambda表达式之变量作用域问题变量作用域 变量作用域 考虑下面这个例子: public static void repeatMessage(String text,int delay){ ActionListener listener = event->{ System.out.println(text); ...
  • python 的lambda 匿名函数遵循和标准函数一样的作用域规则。一个lambda 表达式定义了新的 作用域,就像函数定义,所以这个作用域除了局部lambda/函数,对于程序其他部分,该作用域都是 不能对进行访问的. 那些声明...
  • 函数定义了本地作用域,而模块定义的是全局作用域。如果想要在函数内定义全局作用域,需要加上global修饰符 # 函数变量声明周期 a = 5 # 外部定义变量 def func1 ( ) : # 外面定义变量,在函数内部...
  • lambda表达式:变量作用域

    千次阅读 2015-12-09 09:56:41
    写给大忙人看的JavaSE8中的lambda表达式:变量作用域
  • Java Lambda 表达式(二):作用域引言示例代码总结 引言 正如我们之前在 Java 变量捕获(Captured Variable)和 Java 变量隐藏(Shadow)两篇文章中所说的,局部类和匿名类都存在变量捕获和变量隐藏,而今天我们说...
  • lambda表达式中访问外层作用域和老版本中的匿名对象中的方式相似; 可以直接访问标记了final的外层局部变量,或者实例字段以及静态变量。 要求局部变量必须是被final修饰的。 举例: 1.接口 package ...
  • 为什么80%的码农都做不了架构师?...lambda表达式的作用域被嵌套在doWork()方法中,并且无论this位于方法的何处,其意义都是一样的。 转载于:https://my.oschina.net/fhd/blog/419892
  • 文章目录函数返回值单返回值的函数多返回值的函数返回列表返回元组变量的作用域局部变量全局变量修改全局变量 函数返回值 print("输出:") def hello(): print("hello Tom") temp=hello() # temp的值为 None print...
  • python作用域,变量作用域

    千次阅读 2019-07-02 20:33:02
    变量作用域 一个程序的所有变量并不是在哪个位置都可以访问的。访问权限取决于这个变量是在哪里赋值的。 变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。 如下为两种最基本的变量的作用域: ...
  • python3作用域

    2021-01-20 03:14:39
    2、只有在模块module,类class,函数def、lambda中才可以改变作用域,其他情况不可。 例1 def func(): x= 100 print(x) func() print(x) 报错,因为第二个print(x)找不到变量x 例2 for i in range(4): x = i print...
  • <!DOCTYPE html> <... <head> ...meta charset="UTF-8">...javaScript中var变量的作用域</title> </head> <body> <h1>javaScript中var变量的作用域</h1...
  • 这一章节我们来讨论一下嵌套lambda作用域 我们在前面的章节已经涉及到一些作用域lambda表达式,例如: >>> def test(N): return lambda x:x*N >>> func=test(2) >>&g...
  • 函数的return和作用域

    2019-11-17 23:17:20
    global关键字声明的变量必须在全局作用域上,不能嵌套作用域上,当要修改嵌套作用域(enclosing作用域,外层非全局作用域)中的变量怎么办呢,这时就需要nonlocal关键字了 在这里插入代码片 def outer ( ) : ...
  • 一个函数级变量,但是它的作用域实际上是对象级的。因为在实际的应用中,开始编辑和结束编辑这两个事件发生后,都会对其进行调用,且调用的结果都会有变化。换言之,如果仅是函数内级变量,应该其只能是第一次赋值...
  • 如何在lambda表达式中使用局部变量? Lambda 表达式是 JDK8 的一个新特性,可以取代大部分的匿名内部类,写出更优雅的 Java 代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。 JDK 也提供了...
  • Python中闭包与lambda作用域

    千次阅读 2018-07-03 11:17:04
    Python中闭包与lambda作用域 lambda写法 def fun(): for i in range(3): yield lambda x : x * i f0, f1, f2 = fun() print(f0(1), f1(2), f2(3)) 闭包的写法 def fun(): result = [] for i in rang....
  • Python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的 内置名称(built-in names), Python ...
  • 作用域lambda

    2017-08-02 22:37:58
    一个lambda表达式定义了新的作用域,就像函数定义,所以这个作用域除了局部lambda函数,对于程序其他部分,该作用域都是不能对其进行访问的。 >>> def foo():  y=5  bar=lambda z:x+y  print(bar(y))  y=8 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 31,855
精华内容 12,742
关键字:

lambda作用域