5.Kotlin-泛型

该博客围绕Kotlin泛型展开,虽暂无具体内容,但可知聚焦于Kotlin这门编程语言的泛型特性,泛型在编程中可提高代码复用性和类型安全性,是Kotlin重要的编程概念。
1.泛型(generics)
与java类似,kotlin的类页游类型参数:
class Box<T>(t:T){
var value = t
}
一般情况,使用泛型实例,需要类型参数:
val box : Box<Int> = Box<Int>(1)

如果类型参数可推断出来,可省略类型参数:
val box = Box(1) //1是Int,编译器可推断出Box<Int>

2.型变(Variance)
Java泛型中最棘手部分就是通配符类型,但是kotlin没有
所以kotlin通过型变(Variance)弥补:
声明处型变(declaration-site variance)
类型投影(type projections)
为什么Java泛型需要通配符类型?
在Effective Java解释了该问题-第28条:利用有限制通配符来提升api的灵活性。
Java泛型是不型变的,意味着List<String>不是List<Object>子类型;
如果List是型变的,如下代码编译正常,但运行时出现异常:
List<String> strs = new ArrayList<String>();
List<Object> objs = strs;//错误,Java禁止型变
objs.add(1);
String s = strs.get(0);//运行出现异常
这就是为什么Collection.addAll()实际参数如下:
//Java
interface Collection<E> ...{
//通配符<? exetends E>表示包括E在内的所有子类,称为协变
//通配符<? super E>表示包括E在内的所有父类,称为逆变
void addAll(Collection<? extends E> items);
}
void copyAll(Collection<Object> to, Collection<String> from){
//<? extends E>可以让Collection<String>是Collection<? extends Object>子类型
to.addAll(from);
}
<? extends E>协变:表示包括E在内的所有子类,泛型对象只能读取,称为生产者
<? super E>逆变:表示包括E在内的所有父类,泛型对象只能写入,称为消费者。

3.声明处型变
Java泛型的一个例子:
interface Source<T>{
//只有生产者方法,没有消费者方法
T nextT();
}
void demo(Source<String> strs){
//Source<T>没有消费者方法,型变是安全的,但是java并不知道,所以仍然要禁止
//需要声明类型为Source<? super Object>,这是毫无意义的。
Source<Object> objects = strs;//错误:在Java中不允许型变
}
1.out修饰符
在kotlin中,可用out修饰类型参数T,确保T只能输出(生产),不被消费
out修饰符称为型变注解,使类型参数协变
abstract class Source<out T>{
abstract fun nextT():T
}
fun demo(strs : Source<String>){
val objects : Source<Any> = strs//可以型变,因为T是out
}
2.in修饰符
用in修饰类型参数T,确保T只能被消费,不能输出,使类型参数逆变
abstract class Comparable<in T>{
abstract fun compareTo(other : T):Int
}
fun demo(x : Comparable<Number>){
//1.0拥有Double类,是Number的子类
x.compareTo(1.0)
//Double是Number的子类,父类Number可以被Double消费
val y : Comparable<Double> = x
}
助记符:消费者-输入in, 生产者-输出out
由于in/out在类型参数声明处,所以称为声明处型变。
4.使用处型变/类型投影
类型参数T既不是协变,也不是逆变
class Array<T>(val size : Int){
fun get(index:Int):T{}//生产out
fun set(index:Int, value : T)//消费in
}
fun copy(from : Array<Any>, to : Array<Any>){
assert(from.size == to.size)
for(i in from.indices){
to[i] = from[i]
}
}
val ints : Array<Int> = arrayOf(1,2,3)
val anys = Array<Any>(3){ "" }
copy(ints,anys)//错误:期望(Array<Any>, Array<Any>)
1.out确保from中的Any只生产输出,不被消费,对应于Java的Array<? extends Object>
2.in 确保dest中的String只能被消费,不能生产输出,对应于Java的Array<? super String>

5.星投影<*>
如果对类型参数一无所知,可用星投影:
1.对于Foo<out T>,T是一个具有上界TUpper的协变类型参数,Foo<*>等价于Foo<out TUpper>
当T未知时,可以安全地从Foo<*>读取TUpper的值

2.对于Foo<in T>,T是一个逆变类型参数,Foo<*>等价于Foo<in Nothing>
当T未知时,没有什么方式可以安全写入Foo<*>

3.对于Foo<in T>,T是一个具有上界TUpper的不型变类型参数,
Foo<*>在读取值时等价于Foo<out TUpper>,在写入值时等价于Foo<in Nothing>

如果有多个类型参数,则每个类型参数都可单独投影:
interface Function <in T, out U>
Function<*, String> 表示Function<in Nothing, String>
Function<Int, *>       表示Function<Int, out Any?>
Function<*,*>            表示Function<in Nothing, out Any?>
注意:星投影非常像Java的原始类型,但是安全。

6.泛型函数
和java类型,kotlin不仅类有泛型,函数也有泛型:
//普通函数
fun <T> singletonList(item:T): List<T>{
// 
}
扩展函数
fun <T> T.basicToString() : String{
//
}
//调动泛型函数,在函数名后指定类型参数
val l = singletonList<Int>(1)

7.泛型约束
最常见的约束类型是,与Java的<? extends T>对应的上界:
//<T : Comparable<T>>冒号之后指定类型上界,只有Comparable<T>子类型可以替代T
fun <T:Comparable<T>> sort(list : List<T>){
}
sort(listof(1,2,3))//Int是Comparable<Int>子类型
sort(listof(HashMap<Int,String>())) //错误:HashMap<Int,String>不是		      Comparable<HashMap<Int, String>>子类型  

默认上界是Any?, < : 上界>中只能指定一个上界,如果同一类型参数需要多个上界,需要单独的where语句
fun <T> cloneWhenGreater(list : List<T>, threshold : T) : List<T> where T : Comparable,T:Cloneable{
return list.filter{ it > threshold }.map{it.clone()}
}

[ 95% 474/495] //frameworks/base/services/permission:services.permission kotlinc [common] FAILED: out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlin/services.permission.jar out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlin_headers/services.permission.jar rm -rf "out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc/classes" "out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc/header_classes" "out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc/srcJars" "out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc-build.xml" "out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc/empty" && mkdir -p "out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc/classes" "out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc/header_classes" "out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc/srcJars" "out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc/empty" && out_system/host/linux-x86/bin/zipsync -d out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc/srcJars -l out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc/srcJars/list -f "*.java" out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kapt/kapt-sources.jar && out_system/host/linux-x86/bin/gen-kotlin-build-file --classpath "out_system/soong/.intermediates/build/soong/java/core-libraries/stable.core.platform.api.stubs/android_common/turbine-combined/stable.core.platform.api.stubs.jar:out_system/soong/.intermediates/libcore/core-lambda-stubs/android_common/turbine-combined/core-lambda-stubs.jar:out_system/soong/.intermediates/frameworks/base/ext/android_common/turbine-combined/ext.jar:out_system/soong/.intermediates/frameworks/base/framework/android_common/turbine-combined/framework.jar:out_system/soong/.intermediates/frameworks/base/services/core/services.core/android_common/turbine-combined/services.core.jar:out_system/soong/.intermediates/external/kotlinc/kotlin-annotations/android_common/combined/kotlin-annotations.jar:out_system/soong/.intermediates/external/kotlinc/kotlin-stdlib/android_common/combined/kotlin-stdlib.jar:out_system/soong/.intermediates/external/kotlinc/kotlin-stdlib-jdk7/android_common/combined/kotlin-stdlib-jdk7.jar" --name "frameworks__base__services__permission__android_common__services.permission" --out_dir "out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc/classes" --srcs "out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlin/services.permission.jar.rsp" --srcs "out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc/srcJars/list" --out "out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc-build.xml" && external/kotlinc/bin/kotlinc -Didea.plugins.compatible.build=999.SNAPSHOT -J--add-opens=java.base/java.util=ALL-UNNAMED -J-Xmx4096M -Xjvm-default=all -Xno-call-assertions -Xno-param-assertions -Xno-receiver-assertions -Xsam-conversions=class -no-stdlib -no-jdk -jvm-target 17 -Xbuild-file=out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc-build.xml -kotlin-home out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc/empty -Xplugin=external/kotlinc/lib/jvm-abi-gen.jar -P plugin:org.jetbrains.kotlin.jvm.abi:outputDir=out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc/header_classes && out_system/host/linux-x86/bin/soong_zip -jar -o out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlin/services.permission.jar -C out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc/classes -D out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc/classes -write_if_changed && out_system/host/linux-x86/bin/soong_zip -jar -o out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlin_headers/services.permission.jar -C out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc/header_classes -D out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc/header_classes -write_if_changed && rm -rf "out_system/soong/.intermediates/frameworks/base/services/permission/services.permission/android_common/kotlinc/srcJars" exception: org.jetbrains.kotlin.backend.common.BackendException: Backend Internal error: Exception during IR lowering File being compiled: /home/user256/work/TVE1086/system/frameworks/base/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt The root cause java.lang.RuntimeException was thrown at: org.jetbrains.kotlin.backend.jvm.codegen.FunctionCodegen.generate(FunctionCodegen.kt:49) at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException(CodegenUtil.kt:241) at org.jetbrains.kotlin.backend.common.CodegenUtil.reportBackendException$default(CodegenUtil.kt:236) at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invokeSequential(performByIrFile.kt:68) at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:55) at org.jetbrains.kotlin.backend.common.phaser.PerformByIrFilePhase.invoke(performByIrFile.kt:41) at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.invoke(CompilerPhase.kt:96) at org.jetbrains.kotlin.backend.common.phaser.CompositePhase.invoke(PhaseBuilders.kt:29) at org.jetbrains.kotlin.backend.common.phaser.NamedCompilerPhase.invoke(CompilerPhase.kt:96) at org.jetbrains.kotlin.backend.common.phaser.CompilerPhaseKt.invokeToplevel(CompilerPhase.kt:43) at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.invokeCodegen(JvmIrCodegenFactory.kt:312) at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.runCodegen(KotlinToJVMBytecodeCompiler.kt:348) at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:123) at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli$default(KotlinToJVMBytecodeCompiler.kt:47) at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:167) at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:53) at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:101) at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:47) at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101) at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:79) at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:43) at org.jetbrains.kotlin.cli.common.CLITool$Companion.doMainNoExit(CLITool.kt:179) at org.jetbrains.kotlin.cli.common.CLITool$Companion.doMainNoExit$default(CLITool.kt:177) at org.jetbrains.kotlin.cli.common.CLITool$Companion.doMain(CLITool.kt:166) at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler$Companion.main(K2JVMCompiler.kt:250) at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.main(K2JVMCompiler.kt) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.jetbrains.kotlin.preloading.Preloader.run(Preloader.java:87) at org.jetbrains.kotlin.preloading.Preloader.main(Preloader.java:44) Caused by: java.lang.RuntimeException: Exception while generating code for: FUN name:initialize visibility:public modality:FINAL <> ($this:com.android.server.permission.access.AccessCheckingService) returnType:kotlin.Unit $this: VALUE_PARAMETER name:<this> type:com.android.server.permission.access.AccessCheckingService这个报错是什么原因怎么修复
最新发布
08-09
<think>嗯,用户遇到了一个Kotlin编译错误"Backend Internal error: Exception during IR lowering",这是在编译Android系统源码时出现的。这个问题看起来和Kotlin编译器的内部中间表示(IR)处理有关。 用户可能正在使用IDEA或Android Studio开发Android应用,遇到了这个棘手的编译错误。从错误信息看,这属于Kotlin编译器后端的内部异常,通常比较难直接定位原因。用户应该已经尝试过基本的清理和重建操作但未能解决,所以需要更深入的排查方案。 让我梳理几个关键排查方向: 首先是环境配置问题,特别是Gradle JDK版本。引用[3]提到需要JDK 11+,这很关键,因为Kotlin编译器对JDK版本很敏感。其次是Kotlin版本兼容性,引用[2]指出compose编译器版本需要匹配,这个在Android开发中经常被忽略。另外缓存问题也值得关注,因为不完整的缓存可能导致IR处理异常。 用户可能没意识到的是,这个错误有时是由依赖冲突引起的。比如当不同模块使用不同版本的Kotlin stdlib时,编译器在生成中间代码阶段就会崩溃。还有资源文件错误也可能间接导致IR处理失败,比如XML里包含非法字符。 考虑到这是系统源码编译,建议用户先尝试最稳妥的clean build操作,这能解决50%以上的非常规编译问题。如果无效,就要重点检查JDK版本和Gradle配置,特别是local.properties里的JAVA_HOME设置。升级Kotlin版本也是常用手段,但要注意同步更新所有相关插件。 对于高级用户,启用编译日志和堆栈跟踪能提供关键线索。不过要提醒用户,--stacktrace输出的信息可能很专业,需要一定经验才能解读。如果所有常规方法都失败,可能需要考虑降级Kotlin版本这种回退方案。</think>以下是针对Kotlin编译错误 `Backend Internal error: Exception during IR lowering` 的完整修复方案,结合常见原因和系统级编译场景: --- ### **原因分析与修复步骤** #### 📌 1. **检查Gradle JDK版本** - **问题根源**:Kotlin编译器需要 **JDK 11+** 支持(尤其Android Gradle Plugin 7.0+)[^3] - **操作步骤**: 1. 打开 `File > Project Structure > SDK Location` 2. 确认 **JDK Location** 指向 **JDK 11+** 3. 在终端执行: ```bash ./gradlew -v # 检查Gradle JVM版本 ``` 4. 若需修改全局配置: `File > Settings > Build Tools > Gradle` → 修改 **Gradle JDK** 为JDK 11+ #### 📌 2. **清理构建缓存** Kotlin IR编译器可能因缓存损坏报错: ```bash # 清理项目缓存 ./gradlew cleanBuildCache rm -rf ~/.gradle/caches/build-cache-* # 清理Kotlin特定缓存 rm -rf build/ kotlin-build/ ``` #### 📌 3. **同步Kotlin与Compose版本** - **关键依赖冲突**:`kotlin-gradle-plugin` 与 `compose-compiler` 版本必须兼容[^2] - 在 `build.gradle` 中显式声明版本: ```gradle buildscript { ext.kotlin_version = "1.9.0" // 需≥1.8.20 dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } android { composeOptions { kotlinCompilerExtensionVersion = "1.5.3" // 必须匹配Kotlin版本 } } ``` - 参考[官方兼容表](https://developer.android.com/jetpack/androidx/releases/compose-kotlin)调整版本 #### 📌 4. **检查增量编译问题** 临时禁用增量编译以验证: ```gradle // gradle.properties kotlin.incremental=false kapt.incremental.apt=false ``` #### 📌 5. **排查资源文件错误** Kotlin IR可能因资源文件异常崩溃: - 检查 `res/` 目录下的XML文件是否有语法错误 - 验证资源命名是否包含非法字符(如 `@+id/foo.bar`) #### 📌 6. **启用详细日志** 获取完整错误堆栈: ```bash ./gradlew assembleDebug --stacktrace --info ``` 重点关注 **"Caused by"** 后的堆栈信息,常见诱因: - 推断失败 - 内联函数递归调用 - 实验性API未启用 --- ### **高级修复方案** #### 🔧 1. **升级Kotlin到稳定版** ```gradle // build.gradle ext.kotlin_version = '1.9.22' // 当前最新稳定版 ``` #### 🔧 2. **强制依赖版本统一** 解决传递依赖冲突: ```gradle configurations.all { resolutionStrategy { force 'org.jetbrains.kotlin:kotlin-stdlib:1.9.22' force 'org.jetbrains.kotlin:kotlin-reflect:1.9.22' } } ``` #### 🔧 3. **禁用IR编译器(临时方案)** 在 `gradle.properties` 中回退旧编译器: ```properties kotlin.use.ir.backend=false # 回退至旧版前端编译器 ``` > ⚠️ 此方案仅作临时验证,Compose项目需保持IR开启 --- ### **系统源码编译特殊处理** 针对AOSP项目: 1. 在 `prebuilts/kotlin/` 中检查预置Kotlin版本 2. 更新repo中的Kotlin工具链: ```bash repo sync prebuilts/kotlin ``` 3. 确认环境变量 `JAVA_HOME` 指向JDK 11: ```bash export JAVA_HOME=/path/to/jdk11 ``` --- ### **典错误案例参考** ```log Caused by: java.lang.IllegalStateException: at org.jetbrains.kotlin.ir.util.TransformersKt.transform(Transformers.kt:33) at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.generateModule(JvmIrCodegenFactory.kt:91) ``` 👉 **解决方案**:升级Kotlin至 **1.8.20+** 修复IR转换器缺陷[^1] --- > **结果验证**:完成上述步骤后执行: > ```bash > ./gradlew clean && ./gradlew assembleDebug > ``` > 若问题仍存,请提供 `--stacktrace` 输出中的 **首个"Caused by"** 堆栈信息进一步分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值