Kotlin Noarg Allopen插件的安装使用和测试以及踩过的坑

Kotlin Noarg Allopen插件的安装使用和测试以及踩过的坑(插件似乎不生效问题)

前言:

​ 在kotlin中使用java的部分框架/工具时,尝尝会出现不兼容的问题,这些问题有很大概率是由于kotlin类没有无参构造器或者kotlin类默认final引起的。

​ 同样,我在使用工具类/框架时也遇到了这样的问题,最终的解决办法是引入kotlin官方的 No-arg,All-open插件。

​ 本文假设使用的是IDEA集成开发环境和Gradle管理工具。

安装:

在你的build.gradle文件中

Groovy:
buildscript {
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlin_version"
        classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version"
    }
}

apply plugin: "kotlin-noarg"
apply plugin: "kotlin-allopen"
Kotlin:
plugins {
  id "org.jetbrains.kotlin.plugin.noarg" version "1.7.21"
  id "org.jetbrains.kotlin.plugin.allopen" version "1.7.21"
}

配置和使用:

1.在build.gradle中配置插件必须的属性
noArg {
    //如果您希望插件从合成构造函数运行初始化逻辑,则启用invokeInitializers选项。缺省情况下,它是禁用的。
    invokeInitializers = true
	//注意是全名,不是包名,以我下文为例,这里应该是annotation("com.openaddr.annotation.NoArg")
    annotation("你的自定义注解全引用名")

}

allOpen {
    //annotation("com.openaddr.annotation.AllOpen")
    annotation("你的自定义注解全引用名")
    // annotations("你的自定义注解全引用名", "你的另一个自定义注解全引用名")
}

2.在项目某个路径下创建自定义注解

//例如我在com.addr.annotation包下创建了两个注解
//NoArg代表添加无参构造方法,AllOpen代表给类和方法取消final
package com.addr.annotation

annotation class NoArg
annotation class AllOpen

3.在某个需要添加无参构造方法或者取消final的类上添加自定义注解

package com.addr.model

import com.addr.annotation.AllOpen
import com.addr.annotation.NoArg

//需要哪个功能就添加哪个注解,也可以都添加,甚至你可以在build.gradle中将这两个功能指定为同一个注解,添加一个注解则同时生效两个功能
@AllOpen
@NoArg
//可以是data类,也可是普通类
data class Father(val string: String) {

    fun hello(){
		println("hello from father")
    }
}

验证是否生效(注意有坑!!):

1.坑:

​ 相信读者中有一部分已经想到了,验证是否生效直接用IDEA的反编译工具看一下反编译的结果,根据有没有无参构造,是不是final就可以验证了。确实,它有时候是可以判断的。

​ 然而,据我实测,IDEA的反编译似乎有延迟,或者完全不更新。它显示final或者没有无参构造的时候,实际上根据我实测,其实已经是有了的(尤其是同时加入两个插件,非常容易出现反编译结果不准确,我为此耽误了大量时间)。所以尽量不要依赖此工具验证结果。

​ 建议参考下文的验证方式。

2.验证是否open:

​ 验证open最简单的方式是尝试去继承被@AllOpen标注的类

​ 创建子类,并继承父类(验证类是否open),重写方法(验证方法是否open)

package com.openaddr.model

class Son(string: String) : Father(string) {
    override fun hello() {
        println("hello from son")
    }
}

​ 编译,如果编译通过,说明已经有open了(如果没有open,则会报错)

如果没有open,报错信息:
//类不能被继承
This type is final, so it cannot be inherited from
//方法不能被重写
'hello' in 'Father' is final and cannot be overridden
如果open了则会正常编译通过
3.验证是否有无参构造:

​ 需要注意的是,官方有这样一段声明:

The generated constructor is synthetic so it can't be directly called from Java or Kotlin, but it can be called using reflection.

​ 意思是:

被生成的无参构造器不能被直接被Java或者Kotlin调用,但它可以通过反射的方式调用。

​ 因此,我们验证是不能直接通过无参构造对象来验证的,应该通过反射来构造对象:

package com.openaddr.test

import com.openaddr.model.Father
import com.openaddr.model.Son

fun main() {
    //反射构造
    val father = Father::class.java.getDeclaredConstructor().newInstance()
    println(father)
}

​ 如果能成功输出对象(编译通过),说明无参构造生效了:

Father(string=null)

​ 如果无参构造没有生效,则应该会抛出以下异常:

Exception in thread "main" java.lang.NoSuchMethodException: com.openaddr.model.Father.<init>()
	at java.lang.Class.getConstructor0(Class.java:3082)
	at java.lang.Class.getDeclaredConstructor(Class.java:2178)
	at com.openaddr.test.MainTestKt.main(MainTest.kt:8)
	at com.openaddr.test.MainTestKt.main(MainTest.kt)

进程已结束,退出代码1

至此,如果一切顺利,我们已经成功使用并测试了这两个插件。祝大家kotlin学习顺利。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值