Lambda Expressions

本文详细介绍了Java 8中引入的Lambda表达式,包括其语法、用法及应用场景。通过对比匿名内部类,展示了Lambda表达式如何简化代码,并提供了具体的示例来解释其工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Lambda

匿名内部类已经是一种简洁的表示方法了,但是还有一个问题,例如一个接口,它只含有一个方法,那么匿名内部类就不那么易于使用了,因为会出现很多冗余的代码,这个时候开发者就会想要将函数当成一个参数传递给一个方法,例如为控件设置点击事件。所以就出现了Lambda表达式,Java8引入了这个新特性,使用Android Studio编程时,会发现为控件设置点击事件的代码会“变样”,如下第二种表示方式就是Lambda表达式,既然官方都这样用了,那我们还有什么理由不拥抱这种方式呢。

 view.setOnClickListener(new View.OnClickListener() {//明明是这样写的
            @Override
            public void onClick(View v) {

            }
        });

  view.setOnClickListener((v) -> {//有的时候代码看上去变成了这样

        });  
  • 用法

    • Android Studio配置:

      android {
          buildToolsVersion "24.0.0"//大于24即可
          defaultConfig {
              jackOptions {
                  enabled true
              }
          }
          compileOptions {
              sourceCompatibility JavaVersion.VERSION_1_8
              targetCompatibility JavaVersion.VERSION_1_8
          }
      }
    • 语法

      • Lambda表达式只适用于只含有一个方法的接口
      • Lambda表达式的结构:(Type params) -> {block},整个表达式代表的是“接口的实现类”;params代表这个“接口中的方法的形参”;Type代表“形参的类型”,可以省略;block代表“接口中方法的实现“,具体请看下面的例子;
         public interface ISyntax {//Lambda表达式只适用于只含有一个方法的接口
          int getInt(int i);
      }
      
      private void invokeSyntax(ISyntax s) {//调用这个方法需要传递ISyntax的实现类
          s.getInt(10);
      }
      
      private void learnSyntax() {
          //匿名内部类已经省略了声明对象这个步骤,看起来很简洁了。
          invokeSyntax(new ISyntax() {
              @Override
              public int getInt(int i) {
                  return i++;
              }
          });
      
           // Lambda表达式其实也是匿名的,只不过不仅仅匿了对象名称,还匿了类名,方法名
          invokeSyntax((int i) -> { //这里的int i就是接口ISyntax中的getInt()方法中的参数
              return i++; //大括号中的内容就是getInt()方法的实现
          });
      
          invokeSyntax((i) -> i++);//可以省略参数类型,还可以省略大括号和“return”,直接写返回值
      }
      • 作用域
      import java.util.function.Consumer;
      
      public class LambdaScopeTest {
      
          public int x = 0;
      
          class FirstLevel {
      
              public int x = 1;
      
              void methodInFirstLevel(int x) {
      
                  // The following statement causes the compiler to generate
                  // the error "local variables referenced from a lambda expression
                  // must be final or effectively final" in statement A:
                  //
                  // x = 99;
      
                  Consumer<Integer> myConsumer = (y) -> 
                  {
                      System.out.println("x = " + x); // Statement A
                      System.out.println("y = " + y);
                      System.out.println("this.x = " + this.x);
                      System.out.println("LambdaScopeTest.this.x = " +
                          LambdaScopeTest.this.x);
                  };
      
                  myConsumer.accept(x);
      
              }
          }
      
          public static void main(String... args) {
              LambdaScopeTest st = new LambdaScopeTest();
              LambdaScopeTest.FirstLevel fl = st.new FirstLevel();
              fl.methodInFirstLevel(23);
          }
      }
      This example generates the following output:
      
      x = 23
      y = 23
      this.x = 1
      LambdaScopeTest.this.x = 0
      • 返回类型

        Lambda表达式只含有形参列表和实现代码块,那么Java如何判断一个Lambda表达式代表的究竟是哪个接口的实现类呢?看下面的例子:

         //Target Type
        public interface IInteger {
            void setInt(int i);
        }
        
        public interface IString {
            void setString(String str);
        }
        
        public interface IMultiParams {
            void setString(String str1, String str2);
        }
        
        public interface IReturn {
            String getString(String str);
        }
        
        private void use(IInteger e) {
            e.setInt(1);
        }
        
        private void use(IString t) {
            t.setString("IString");
        }
        
        private void use(IMultiParams m) {
            m.setString("param1", "param2");
        }
        
        private void use(IReturn r) {
            r.getString("IReturn");
        }
        
        public void learnTargetType() {
            //IInteger
            use((int i) -> {//该Lambda代表的是IInteger的实现类,因为参数声明了为int类型
                Log.d(TAG, "i: " + i);
            });
            //IString
            use((String str) -> {
                Log.d(TAG, "str: " + str);
            });
            //IMultiParams
            use((param1, param2) -> {
                Log.d(TAG, "param1: " + param1 + " param2: " + param2);
            });
            //IReturn
            use((String str) -> "我有返回值" + str);
        }

        官网总结了以下几点判断Target Type(目标类型)的方法

        • Variable declarations 变量声明

        • Assignments

        • Return statements 返回值声明

        • Array initializers 数组初始化

        • Method or constructor arguments 方法或构造函数参数

        • Lambda expression bodies Lambda表达式代码块

        • Conditional expressions, ?: 条件表达式

        • Cast expressions

    • 优点

      • Lambda表达式其实就是匿名函数,简洁,去除了没有实际意义的代码;
    • 缺点
      • 这个也不算是缺点,使用Lambda表达式必须要对函数非常的熟悉,知道它含有什么参数;

参考文章:Oracle官网Android开发者网站

<think>好的,我现在需要解决用户在Java中遇到的Lambda表达式不被支持的问题,具体错误是“Lambda expressions not supported at language level '7’”。首先,我得回忆一下Java的版本特性。Lambda表达式是在Java 8引入的,所以如果项目语言级别设置为7或更低,编译器肯定不支持Lambda语法。用户的问题应该就是项目配置的语言级别不对。 接下来,我需要考虑可能的解决方案。首先想到的是检查IDE中的项目设置,确保语言级别设置为8或更高。比如在IntelliJ IDEA中,可以在Project Structure里调整Modules和Project的Language Level。如果用户用的是其他IDE,比如Eclipse,可能需要检查对应的编译器设置,确保使用Java 8。 然后,构建工具比如Maven或Gradle也可能影响语言级别。如果项目使用Maven,需要在pom.xml中指定正确的source和target的版本,加入maven-compiler-plugin的配置,设置成1.8。Gradle的话,则需要在build.gradle中设置sourceCompatibility和targetCompatibility为1.8。 另外,用户可能需要确认自己安装的JDK版本是否是8或更高。如果JDK版本过低,即使设置了语言级别,也无法编译Lambda表达式。这时候需要建议用户升级JDK或者调整环境变量指向正确的JDK版本。 还有可能用户没有正确启用Java 8的支持,特别是在一些旧版本的IDE中,可能需要手动开启对新特性的支持。例如,在IntelliJ中,有时候需要检查Settings中的Java Compiler选项,确保选择的编译器版本正确。 同时,需要提醒用户在修改配置后,执行清理和重新构建项目,以确保更改生效。可能还需要重启IDE,特别是当配置更改后没有立即生效的情况下。 最后,如果用户遇到其他相关问题,可能需要进一步检查依赖或插件是否兼容Java 8,或者是否有其他配置覆盖了语言级别的设置。这时候建议用户提供更多上下文信息,以便更精准地解决问题。</think>针对Java中出现的“Lambda表达式在语言级别7不支持”的问题,以下是逐步解决方案: --- ### **步骤1:确认JDK版本** Lambda表达式是Java 8引入的特性[^1]。 - 检查当前使用的JDK版本: ```bash java -version ``` 确保输出为`1.8.x`或更高版本。 - 如果版本低于8,需[下载并安装JDK 8+](https://www.oracle.com/java/technologies/downloads/)。 --- ### **步骤2:配置IDE的语言级别** 以**IntelliJ IDEA**为例: 1. **修改项目语言级别**: - 打开 `File > Project Structure > Project Settings > Project` - 将 `Project language level` 设置为 **8+**。 2. **修改模块语言级别**: - 在 `Project Structure > Modules` 中,确保每个模块的语言级别为 **8+**。 --- ### **步骤3:配置构建工具(如Maven/Gradle)** #### **Maven** 在`pom.xml`中指定Java 8: ```xml <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> ``` #### **Gradle** 在`build.gradle`中添加: ```groovy sourceCompatibility = 1.8 targetCompatibility = 1.8 ``` --- ### **步骤4:清理并重新构建项目** - 在IDE中执行清理操作(如 `Build > Rebuild Project`)。 - 如果使用Maven/Gradle,运行: ```bash mvn clean install # Maven ./gradlew clean build # Gradle ``` --- ### **步骤5:检查IDE插件兼容性** 某些旧版本插件可能与Java 8不兼容。建议: - 更新IDE至最新版本。 - 禁用或更新与Java版本相关的插件[^2]。 --- ### **常见问题** 1. **仍报错?** 确保IDE未缓存旧配置,尝试重启IDE。 2. **多模块项目?** 检查所有模块的语言级别设置。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值