首页 > 编程语言 >Java Lambda 表达式中为何不能访问局部定义的变量?

Java Lambda 表达式中为何不能访问局部定义的变量?

时间:2024-06-22 15:46:49浏览次数:13  
标签:Java Thread lambda str new test01 final 表达式 Lambda

问题展示代码:

    public static void test01() {
        String str = "str";
        new Thread(()->{
            str += "yes";
            System.out.println(str);
        }).start();
    }

在jdk1.8下, 在lambda表达式中访问str, 编译器未报错; 提示我不可访问非final的局部变量;这是我对str值改变的情况下; 当我们不改变str的值, 去访问str时, 却不会报错, 如下代码:

    public static void test01() {
        String str = "str";
        new Thread(()->{
            System.out.println(str);
        }).start();
    }

不对啊, 我的str并没有修饰成final啊, 只是未修改它的值而已, 为什么这次不会报错了呢? 其实吧! str此时的str就是一个final修饰的变量啊, 因为从头到尾, str并没有发生过任何修改, 它就是一个final;
我们对程序稍作更改:

    public static void test01() {
        String str = "str";
        new Thread(()->{
            System.out.println(str);
        }).start();
        
        str = "zhang";
    }

我们main方法的尾部处, 将str的值改变了, 现在又开始编译错误了, 这说明str失去了final的特性了;
所以关于lambda不能访问非final修饰的变量的定义应该改为, lambda不能访问无final特性的局部变量;

为什么lamda不能访问非final特性的局部变量呢?

都知道lambda只是匿名内部类实现的一种简化写法, lambda会创造一个实现类且返回一个实现类的实例;
仔细分析一下这个程序:

    public static void test01() {
        String str = "china";
        new Thread(()->{
            System.out.println(str);
        }).start();

        str = "zhang";
    }

我们可以认为test01这个方法为主线程, new Thread会新建一个线程并进行执行. 线程的执行实际是并发的, 这段程序并不能保证完完全全是按照主线程test01去顺序执行的. 此时主线程中我将str的值改为了"zhang",
那子线程如果支持这样的非final特性的局部变量在其中的方法中执行的话, 你能保证str的值的同步性吗?
并发的原因, 似乎并不可能, 说不定子线程输出的是主线程改变str后的值. 而在业务逻辑上, 我需要的是"china"这个值. 所以Java组织了这种用法, 用于规避线程之间的数据不同步问题;

问题1: 显式修饰为final的局部变量为何可以使用?
    public static void test01() {
        final int a = 0;
        new Thread(()->{
            System.out.println(a);
        }).start();
    }

因为final修饰的变量是无法改变了, 不会存在并发导致的数据不同步问题;

问题2: 为什么非显式修饰的局部变量, 只有不改变值, 也可以在lambda表达式中使用?
    public static void test01() {
        int a = 0;
        new Thread(()->{
            final int a = 0;   // 假设编译通过
            System.out.println(a);
        }).start();
    }

你可以这样去想象;
你也许还会有一个问题: 我在Lambda之外修改了, 还是会引发编译错误啊! 答案之前告诉过你, 因为并发, 你能确定在lambda里赋值的final变量和主线程的是同步的吗? 你不能的!

标签:Java,Thread,lambda,str,new,test01,final,表达式,Lambda
From: https://www.cnblogs.com/zhangyuzhijia/p/18262348

相关文章

  • 大学生HTML期末大作业——HTML+CSS+JavaScript旅游网站
    HTML+CSS+JS【旅游网站】网页设计期末课程大作业web前端开发技术web课程设计网页规划与设计......
  • 大学生HTML期末大作业——HTML+CSS+JavaScript影视网站(爱美剧)
    HTML+CSS+JS【影视网站】网页设计期末课程大作业web前端开发技术web课程设计网页规划与设计......
  • java_if判断语句
    顺序结构JAVA的基本结构就是顺序结构,除非特别指明,否者就按照顺序一句一句执行。顺序结构是最简单的算法结构。语句与语句之间,框与框之间是按照从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的,他是任意一个算法都离不开的一种基本算法结构。packagecom.wen.s......
  • 基于Java中的SSM框架实现一汽租车共享平台系统项目【项目源码+论文说明】计算机毕业设
    摘要随着人们生活水平的不断提高,人们租车进行旅游的行为已成为大家的不二选择。汽车租赁服务被称为交通运输服务行新兴的服务行业,因为汽车租赁无须办理保险、无须年检维修、车型可随意更换等优点,以租车代替买车来控制企业成本,其实这种汽车管理方式在外企中是十分流行的方......
  • java中Optional的应用,以及map和flatMap的区别
    关于Option的介绍可以看深入理解java8中的Optional类就可以了,但是复杂一点的使用在网上却没有搜到,这里结合我开发时遇到的真实案例来讲一下Option的使用。1.案例一在真实业务操作过程中,都是对象里面套对象,这边先简单定义操作对象:publicclassPictureCondition{privateStri......
  • java网络编程 , 网络编程 , Junit单元测试概念及使用方法详细介绍
    网络编程主要内容网络编程TCP通信Junit单元测试1网络编程1.1软件架构C/S结构:全称为Client/Server结构,是指客户端和服务器结构。常见程序有QQ、迅雷等软件B/S结构:全称为Browser/Server结构,是指浏览器和服务器结构。常见浏览器有谷歌、火狐等两种架构各有优势,但......
  • java单例设计模式 , 多例设计模式 , 工厂设计模式概念及详细介绍
    单例设计模式正常情况下一个类可以创建多个对象publicstaticvoidmain(String[]args){ //正常情况下一个类可以创建多个对象 Personp1=newPerson(); Personp2=newPerson(); Personp3=newPerson();}如果说有时一个对象就能搞定的事情,非要创建多......
  • Java 接口
    本篇学习接口,并区分接口与抽象类两者之间的异同点。上篇已经讲解了抽象类,有需要的小伙伴可以点链接康康https://blog.csdn.net/m0_73107796/article/details/139863674目录1、什么是接口2、接口定义格式3、接口的使用 4、接口特性5、抽象类与接口的区别 1、什......
  • DVWA 靶场 JavaScript 通关解析
    前言DVWA代表DamnVulnerableWebApplication,是一个用于学习和练习Web应用程序漏洞的开源漏洞应用程序。它被设计成一个易于安装和配置的漏洞应用程序,旨在帮助安全专业人员和爱好者了解和熟悉不同类型的Web应用程序漏洞。DVWA提供了一系列的漏洞场景和练习环境,用户可以通过......
  • .Net开发 ,Java开发 ,python开发 数据库开发,开发相关工具
    开发电脑安装相关工具软件Java开发Java编程、高级编程、面试题资料Python编程,网络编程,爬虫,面试,设计资料数据库mysql,sqlservice,sql优化资料C#语言、.Net开发、.Net高级编程资料......