太长不看版

当你的 Android gradle plugin 版别低于 4.2时(后面简称为AGP)。Android Studio(后简称AS) 默许运用 java7 作为语法检查。

当你的代码,或许你依靠的代码中存在 java8 种的语法,比方 lambda。 而且你没有增加 java8 兼容装备。AS在语法分析,或许编译的时候,都会报错。

lambda expressions are not supported in -source 7

为了处理这个报错,能够经过三种方法处理。

  1. 代码中消除 java8 的lambda。(很难做到)
  2. 增加 java8 的兼容装备 (简单做到)
  3. 升级 AGP 到 4.2 (中等难度)

所以,为了处理这个过错,挑选方法 2 是较为简单的。

遇到了问题

项目是一个混合 Flutter 的项目,运用到了 flutter shared_preferences。 在4.15日打包失利,过错提示为:

.../flutter/.pub-cache/hosted/pub.flutter-io.cn/shared_preferences_android-2.1.1/android/src/main/java/io/flutter/plugins/sharedpreferences/Messages.java:84: error: static interface methods are not supported in -source 7
static[@nonnull](https://github.com/nonnull)MessageCodec getCodec() {  
^  
(use -source 8 or higher to enable static interface methods)  
.../flutter/.pub-cache/hosted/pub.flutter-io.cn/shared_preferences_android-2.1.1/android/src/main/java/io/flutter/plugins/sharedpreferences/Messages.java:103: error: lambda expressions are not supported in -source 7  
(message, reply) -> {  
^  
(use -source 8 or higher to enable lambda expressions)  
2 errors

检查 shared_preferences 依靠为 ^2.10.0。 最近一周没有改正这个依靠,而且最近打包都是正常的。

在搜索引擎中搜索 -source 8 or higher to enable lambda expressions 提示应该在项目中增加

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

可是主项目现已增加过这个代码块了,难道要改 shared_preferences?

查找处理方案

查找 flutter shared_preferences github 。发现有这个 issue

[(github.com/flutter/flu…)]

有人回复能够经过如下方法处理

Android gradle 中为什么要添加 java8 兼容配置?

dependency_overrides:
  shared_preferences_android: 2.1.0
  shared_preferences_ios: 2.1.0

能够看出是写死了 flutter 依靠的版别号。

flutter^2.10.0代表取 2.10.x 的最高版别。去掉 ,就是写死版别号。

持续看这个 issue ,后面有人发了另外一个处理方法

Android gradle 中为什么要添加 java8 兼容配置?

对应的 pr[github.com/flutter/pac…]

对应的代码片段如下:

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8 
    targetCompatibility JavaVersion.VERSION_1_8
 }

确实是在 shared_preferencesbuild.gradle 中增加的,也处理了问题,不再报错。

考虑: 为什么能够这样处理

问问 chatgpt 下面这段代码是什么意思?

: Android 中下面这段代码是什么意思

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8 
    targetCompatibility JavaVersion.VERSION_1_8
}

:

这段代码是在 Android build.gradle 文件中的装备选项,它指定了 Java 代码编译时所运用的源码和方针代码兼容性版别都为 Java 8。
- `sourceCompatibility JavaVersion.VERSION_1_8` 表明源码兼容性版别为 Java 8。
- `targetCompatibility JavaVersion.VERSION_1_8` 表明方针代码兼容性版别为 Java 8。
这意味着你能够在你的代码中运用 Java 8 的新言语特性和 API,而且编译后的 APK 能够在支撑 Java 8 的设备上运转。

反问自己:理解了吗?

自问自答:没有。

测验:假如在我的项目里去掉 sourceCompatibility JavaVersion.VERSION_1_8 会怎样样?

IDE 直接摆烂

Android gradle 中为什么要添加 java8 兼容配置?

猜想: Android Studio 默许运用 Java 7 用于代码检查,以及编译吗?

验证猜想

前置准备

1: 需求用的指令

javap -v file

经过这个指令,能够得到 .class 文件对应的java编译版别

2: Android项目中编译出来的 .class 文件在哪里?

Android项目中,java文件的编译产品目录为:

app/build/intermediates/javac/debug/compileDebugJavaWithJavac

假如你发现这个目录下是空的,试试下面几个方法

  • 确定你的现已 rebuild 成功
  • 删除 build 目录,而且 rebuild 项目
  • 假如你没有 java 代码,都是 kotlin 代码,那么这个目录肯定是空的。写一个 java 类吧。
验证场景一: 删除 java_1.8 兼容性代码, 运转指令 javap -v MainActivity.java

得到以下信息

Android gradle 中为什么要添加 java8 兼容配置?

上图中的 major version: 51 表明这个文件是由 java7 编译的。

验证场景二: 保留 java_1.8 兼容性代码, 运转指令 javap -v MainActivity.java

得到以下信息

Android gradle 中为什么要添加 java8 兼容配置?

上图中 major version: 52 表明这个文件是由 java 8 编译的。

开始定论:Android Studio 默许用 java7 编译代码。

假如需求 java8 的语法,比方 lambda,需求额定加上

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8 
    targetCompatibility JavaVersion.VERSION_1_8
}

上面的定论是有误的,下面持续说为什么过错。

再考虑:是谁决议了这个编译版别的?

考虑一:项目怎样用 java7 来编译了?

Android Studio 中,JDK 的版别号现已是 java8 或许是 java11。 我绝对不会指定 java7来编译项意图。

Android gradle 中为什么要添加 java8 兼容配置?

考虑二:sp的开发者有那么不专业吗?

shared_preferences_android 项目,提交 2.1.11版别的那位开发同学。 详细提交 commit [github.com/flutter/pac…]

他写这些代码的时候,IDE直接也报错了吧,还能提交吗?不可能这么不专业吧。

因而我猜想有其他工具,来确定项目运用什么版别的 java 来编译。

猜想一: 是 gradle 决议项意图java编译版别吗?

验证猜想:直接问 chatgpt

问:android gradle 会运用什么java版别来编译android项目?

答:

根据官方文档,Android Gradle插件默许运用Java 8版别来编译Android项目。然而,从Android Gradle插件3.0版别开始,还支撑运用Java 7或更高版别来编译Android项目。
开发者能够在build.gradle文件中的android {}代码块中经过设置compileOptions {}来指定运用的Java版别。例如,设置为Java 7:
android {
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_7
    targetCompatibility JavaVersion.VERSION_1_7
  }
}

注意,要在项目中运用Java 8的新特性(例如Lambda表达式),需求在运用模块的build.gradle文件中增加以下代码来启用Java 8言语功能:
android {
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }

  // For Java 8 language support
  jackOptions {
    enabled true
  }
}

可是从Android Gradle插件3.0版别开始,官方现已弃用Jack编译器,主张运用Java 8言语功能时,运用D8或R8编译器。

chatgpt得到的答案为 Android Gradle Plugin ,简称 AGP,决议了Android项意图java编译版别。

那么 AGP 版别和 Java编译版别的联系是什么呢?

阅读了 AGP 发布的日志 developer.android.google.cn/build/relea…

Android gradle 中为什么要添加 java8 兼容配置?

发现 AGP 从 4.2 版别开始,默许运用 java8 来编译代码,而且 AS 以 java8 作为检查基准,就是图片中的 language level

能够得到定论: 当你的 AGP 版别高于或等于 4.2 ,你不需求增加

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }

也能够运用 java8 语法糖,编译器会默许运用 java8 来编译你的代码。

小结:项意图编译版别默许是 AGP 版别决议的。或许你能够增加兼容性代码来决议编译版别。

回答上面的猜忌二:

shared_preferences_android 项目,提交 2.1.11版别的那位开发同学。 详细提交 commit 他写这些代码的时候,IDE直接也报错了吧,还能提交吗?不可能这么不专业吧。

查看 shared_preferences_android 2.11.1agp 版别

github.com/flutter/pac…

Android gradle 中为什么要添加 java8 兼容配置?

AGP 7.2.2 默许运用 java8 来编译项目。 所以提交 shared_preferences_android lambda 代码的开发者,项目不会报错。

因而能够得到如下小结:项目中 AGP 版别为 4.1.2,默许运用 java7 编译项目, 第三方依靠的 AGP 即便设置到高版别,也会运用 主项意图低版别 AGP

假如第三方依靠要运用 java8 lambda,必须增加兼容装备。

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }