kotlin调用java
可空性
java所有的对象都是可为空的,但是编译器并不知道.因此kotlin在编译期间无法进行安全检测.java返回的可空类型称为平台类型String!
//java
public class TestNull {
public String hello(){
return "hello";
}
public String helloNull(){
return null;
}
}
//kotlin
var j = TestNull()
j.hello().run { println(this.javaClass) }
j.helloNull()?.run { println(this.javaClass) }
如果不用安全操作符?. ,会抛出空指针异常
类型映射
在运行时,所有的kotin类型最终都会映射回java的类型.比如Int - int
属性访问
kotlin使用java的属性,不需要调用getter/setter方法.会自动映射
java调用kotlin @file:JvmName("KK")
- 全局方法可以直接用Kotlin文件的名字+Kt来作为类名调用.实际上是因为Kotlin中的全局方法都被转化为了静态方法包含在一个以Kt结尾的类中
- 可以通过
@file:JvmName("KK")
来重命名kotlin编译出来的类的名字
//TestNull.java
public class TestNull {
public static void main(String[] args) {
System.out.println(KotlinJavaKt.methodInKotlin());
}
}
//kotlinJava.kt
fun methodInKotlin() = "hello I am kotlin"
//等价于
public final class KotlinJavaKt {
@NotNull
public static final String methodInKotlin() {
return "hello I am kotlin";
}
}
java 调用kotlin的属性 @JvmField
通过 @JvmField
标记的属性,可以在java中直接访问,否则需要通过属性提供默认getter/setter方法访问.
class KotlinJava {
@JvmField
var kotlinProperty:String = "kotlin property"
}
public static void main(String[] args) {
KotlinJava kj = new KotlinJava();
System.out.println(kj.kotlinProperty);
}
java调用kotlin的方法支持重载
- @JvmOverloads协助生成kotlin的带默认参数的方法的重载方法
- 默认情况下,kotlin带默认构造参数的方法,是不需要传入多个参数的.
在java中调用必须传入,为了也支持默认参数,需要使用
@JvmOverloads
注解标记. 这个标记的作为是在编译生成的class中添加了多个重载的方法实现
fun defaultParamMethod(name:String = "jack" , age:Int = 10){
println("$name at $age")
}
KK.defaultParamMethod("jimmy" );
//提示错误 defaultParamMethod(java.lang.String, int)' in 'KK' cannot be applied to '(java.lang.String)
//添加注解后可以正常使用
@JvmOverloads
fun defaultParamMethod(name:String = "jack" , age:Int = 10){
println("$name at $age")
}
java 调用伴生对象方法 @JvmStatic
- @JvmField 静态方式调用伴生对象中的属性
- @JvmStatic 静态方式调用伴生对象中的方法
//kotlin
class KotlinJava {
@JvmField
var kotlinProperty:String = "kotlin property"
companion object {
@JvmField
val KOTLIN_VAL = "KOTLIN_VAL"
@JvmStatic
fun readSomething() = print("read func in kotlin")
}
}
//java
public static void main(String[] args) {
System.out.println(KK.methodInKotlin());
KotlinJava kj = new KotlinJava();
KotlinJava.Companion.getKOTLIN_VAL();
//没加@JvmStatic
KotlinJava.Companion.readSomething();
KotlinJava.readSomething();
//加@JvmStatic
System.out.println(KotlinJava.KOTLIN_VAL);
}
java 捕获kotlin的异常
- 默认情况下kotlin中抛出的异常,在java中不会提示异常捕获
- 可以通过catch(Exception) 或者添加 @Throws,让java中提示该异常
- 如果未特殊处理,kotlin中的异常都会被转化为throwable,通过catch(XXException)无法捕获
fun exceptionTest(){
throw IOException()
}
//java
try{
KK.exceptionTest();
}catch (Exception e){
System.out.println("exception found");
e.printStackTrace();
}
@Throws(IOException::class)
fun exceptionTest(){
throw IOException()
}
try{
KK.exceptionTest();
}catch (IOException e){
System.out.println("exception found");
e.printStackTrace();
}
java调用kotlin的函数类型
- kotlin中的函数类型和匿名函数,在java中都被转化为FunctionN来表示,N代表函数类型的参数个数.
- FunctionN(0-22) 可以通过invoke方法触发方法调用
var anonymousMethod :(x:Int ,y:Int)->Unit = {x,y->
println("$x - $y")
}
KK.getAnonymousMethod().invoke(10 ,20);
在android中使用kotlin
工程
新建android 工程时,语言选择kotlin,自动会添加好kotlin的依赖,主要包含
- kotlin的构建插件 ,语言特性相关插件
buildscript {
ext.kotlin_version = '1.6.20-RC2'
repositories {
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:7.0.4"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin-android'
- 使用库相关包括函数扩展如Strings ,Ranges,Collections等.
dependencies {
implementation "androidx.core:core-ktx:+"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}
支持viewbinding
为了简化findViewById,可以选择支持kotlin-parcelize
plugins {
id 'com.android.application'
id 'kotlin-parcelize'
}
import com.hch.kotlinstudy.databinding.ActivityMainBinding
class HomeActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
Log.d("KotlinStudy" , "homeactivity")
binding.tv.text = "hch"
binding.button.setOnClickListener{
Toast.makeText(this , binding.tv.text , Toast.LENGTH_LONG).show()
}
}
}