kotlin 注解初探

作者: 乐之飞于 | 来源:发表于2017-10-15 16:52 被阅读25次

写在前面的话:(如果你懂得javaPoet的原理,那么看此篇文章会一点都不费事!但看100遍不如自己撸一遍)
KotlinPoet 它是什么?
是一个用于生成.kt源文件的Kotlin和Java的 API。
源文件生成在进行诸如注释处理或与元数据文件(例如,数据库模式,协议格式)交互等操作时可能是有用的。通过生成代码,您不需要编写引用,同时也为元数据保留真实的单一来源。
比如:
这是一个Helloworld类:


class Love(name: String) 
{ 
val name: String = name fun greet() 
{ println("Hello, $name") }
}
fun main(args: Array<String>) 
{
 Love(args[0]).greet()
}

使用KotlinPoet生成它:


val greeterClass = ClassName.get("", "Love")
val kotlinFile =KotlinFile.builder("", "HelloWorld")
.addType(TypeSpec.classBuilder("Love") .primaryConstructor(FunSpec.constructorBuilder() .addParameter(String::class, "name") .build()) 
.addProperty(PropertySpec.builder(String::class, "name") .initializer("name") .build()) 
.addFun(FunSpec.builder("love") 
.addStatement("println(%S)", "Hello, \$name") .build()) .build()) 
.addFun(FunSpec.builder("main")
.addParameter(ArrayTypeName.of(String::class), "args") 
.addStatement("%T(args[0]).greet()", loveClass) .build()) .build()
kotlinFile.writeTo(System.out)

使用kotlinpoet生成kotlin代码的时候通常会遇到这样一个问题
比如我希望生成这样一段kotlin代码:


var string: String? = null
string = bundle.get("test") as %T

当我直接把element.asType().asTypeName()作为参数传给%T(假如这个元素element是String类型(或者是其他需要从Java类型映射到kotlin类型的数据类型),最终会生成这样一段代码:


var string: String? = null
string = bundle.get("test") as java.lang.String

这时候编译器就会报错,因为注解处理器是javac提供的一个工具,它只认识Java代码,所以注解处理器中的所有元素element都是Java中的数据类型,因此element.asType().asTypeName()生成的类型就是java.lang.String,然后将其强制转化成kotlin.String当然就报错了,平时不会出现这种错误是因为kotlinc在编译的时候帮我们完成了java.lang.String->kotlin.String的映射,所以没有问题。
在kotlin的反射库kotlin-reflect源码中找到了这么一个类JavaToKotlinClassMap,大致阅读了一下源码发现这个类里面有我们想要的东西,最终我们为Element定义一个扩展方法:


    /**
     * 获取需要把java类型映射成kotlin类型的ClassName  如:java.lang.String 在kotlin中的类型为kotlin.String 如果是空则表示该类型无需进行映射
     */
    private fun Element.javaToKotlinType(): ClassName? {
        val className = JavaToKotlinClassMap.INSTANCE.mapJavaToKotlin(FqName(this.asType().asTypeName().toString()))?.asSingleFqName()?.asString()
        return if (className == null) {
            null
        } else {
            ClassName.bestGuess(className)
        }
    }

在需要获取类型的地方这样调用即可:


val className = element.javaToKotlinType() ?: element.asType().asTypeName()

Gradle集成方式:
compile 'com.squareup:kotlinpoet:0.2.x'

相关文章

  • kotlin 注解初探

    写在前面的话:(如果你懂得javaPoet的原理,那么看此篇文章会一点都不费事!但看100遍不如自己撸一遍)Kot...

  • Kotlin初探(二)数据加载

    内容 Part 1:Kotlin初探(一)基础构建 Part2:Kotlin初探(二)数据加载 UI界面就是一个简...

  • Kotlin注解入门

    Kotlin使用annotation class关键字来定义注解。 一、定义注解 Kotlin不允许为注解定义注解...

  • Kotlin使用注解

    Kotlin的反射也提供了一些支持注解的API。 一、提取注解信息 Kotlin使用kotlin.Annotion...

  • 编译时注解器初探(一)

    编译时注解器初探(一) 注解处理器 (Annotation Processor) 编译时注解和运行时注解定义的方式...

  • Kotlin元注解

    Kotlin在kotlin.annotation包下提供了4个Meta注解(元注解),这4个元注解都用于修饰其他的...

  • 50 篇 Android 干货文章

    目录 热门技术 View 代码封装 源码分析 精进之路 热门技术 Kotlin初探 Kotlin成了Google的...

  • 初探Spring注解

    初探Spring注解 1.@Resource注解 2.@Component 3.@Autowired和@Resou...

  • Kotlin Coroutine 原理解析

    上一篇文章《Kotlin Coroutine 初探》向大家介绍了 Kotlin Coroutine 的由来、重要概...

  • Android 技术干货系列(一)

    目录 热门技术 View 代码封装 源码分析 精进之路 1 热门技术 Kotlin初探 Kotlin成了Googl...

网友评论

    本文标题:kotlin 注解初探

    本文链接:https://www.haomeiwen.com/subject/zoecuxtx.html