###基本互操作

####属性的读写

#####Kotlin能够自动识别Java的Getter与Setter,因此Kotlin中可以使用.的方式去使用Java类的属性:

//Java中的类
public class JavaBean {private int i;public int getI() {return i;}public void setI(int i) {this.i = i;}
}//Kotlin中可以直接通过.操作符去访问Java的属性
val bean = JavaBean()
bean.i = 10
println(bean.i)
复制代码

#####Java操作Kotlin的属性

//Kotlin中的Bean,注意属性为var的时候,在Java中才会有set方法生成
data class KotlinBean(var i: Int)//在Java中可以访问Kotlin的Bean,通过getter/setter
KotlinBean bean = new KotlinBean(0);
bean.setI(10);
System.out.println(bean.getI());
复制代码

####空类型

Kotlin在编译的时候,会对值进行空检查,但是在Java里面没有。所以在Kotlin操作Java代码的时候就会遇到平台类型的问题,这时候开发者需要自己确保非空。

当然可以通过下面两种注解来解决这个问题:

@Nullable  --  相当于Kotlin中的可空类型?
@notnull   --  相当于Kotlin中的一般非空类型
复制代码

####函数的调用

Kotlin中的包级函数,Kotlin在编译的时候会为这些包级函数生成一个类。在Java中就是相当于静态方法的调用。

扩展方法:带Receiver的静态方法
运算符重载:带Receiver的对应名称的静态方法
复制代码

####常见注解

@JvmField 将属性编译成Java变量
@JvmStatic 将对象的方法编译成Java静态方法
@JvmOverloads 默认参数生成重载方法
@JvmName 指定Kotlin文件编译后的类名,默认是文件名+Kt
复制代码

####NoArg与Allopen

生成无参数构造支持Jpa注解,如@EntityAllopen去掉final支持Spring注解,例如@Component
支持自定义注解类型,例如@PoKo
复制代码

####泛型

通配符Kotlin的*对应Java的?因为Kotlin中?的用处多协变与逆变out、in与Java不一样:ArrayList<out String>
没有Raw类型Java中的List相当于Kotlin中的List<*>
复制代码

###SAM转换

SAM转换就是,当Kotlin使用Java接口的时候,当接口里面只有一个方法,那么就可以用Lambda表达式代替。

例如,我们有下面的Java代码:

public class SamJava {private List<Runnable> mRunnables = new ArrayList<>();public void addTask(Runnable runnable) {mRunnables.add(runnable);System.out.println("add:" + runnable);System.out.println(mRunnables.size());}public void removeTask(Runnable runnable) {mRunnables.remove(runnable);System.out.println("remove" + runnable);System.out.println(mRunnables.size());}}
复制代码

那么在Kotlin中可以有两种方式调用,其中,第二种方式就是SAM转换:

fun main(args: Array<String>) {val sam = SamJava()sam.addTask(object : Runnable {override fun run() {println("run1")}})//sam转换sam.addTask { println("run2") }
}
复制代码

####SAM转换的注意事项

SAM转换的原理:通过分析Kotlin的字节码的时候发现,编译器编译成字节码的时候,会将Lambda转换为对应的接口对象。

因此在使用SAM转换的时候就需要注意了,SAM转换实际上是会创建不同的接口对象,对象会存在多个,如下面的代码,Task不能够正确移除:

fun main(args: Array<String>) {val sam = SamJava()val lambda = {println("run")}sam.addTask(lambda)sam.addTask(lambda)sam.removeTask(lambda)sam.removeTask(lambda)
}
复制代码

打印的结果是:

add:com.nan.sam.SamKotlinKt$sam$Runnable$13141d62@2f0e140b
1
add:com.nan.sam.SamKotlinKt$sam$Runnable$13141d62@7440e464
2
removecom.nan.sam.SamKotlinKt$sam$Runnable$13141d62@49476842
2
removecom.nan.sam.SamKotlinKt$sam$Runnable$13141d62@78308db1
2
复制代码

可以发现,在每次进行SAM转换的时候,都创建了不同的Runnable对象,因此remove不成功。

####拓展

SAM转换是对Java代码的转换,但是在中使用接口的时候,就必须要使用传统的方式了:

fun main(args: Array<String>) {val samKtlin = SamKotlin()samKtlin.addTask(object : Runnable {override fun run() {}})
}class SamKotlin {private val mRunnables = ArrayList<Runnable>()fun addTask(runnable: Runnable) {mRunnables.add(runnable)println("add:" + runnable)println(mRunnables.size)}fun removeTask(runnable: Runnable) {mRunnables.remove(runnable)println("remove" + runnable)println(mRunnables.size)}}
复制代码

但是可以通过类型别名的方式来实现类似SAM转换的功能:

//定义类型别名
typealias Runnable = () -> Unitfun main(args: Array<String>) {val samKtlin = SamKotlin()samKtlin.addTask {println("run")}
}
复制代码

但是这样做的话,在Java中使用由会比较麻烦:

SamKotlin samKotlin = new SamKotlin();
samKotlin.addTask(new Function0<Unit>() {@Overridepublic Unit invoke() {return null;}
});
复制代码

###正则表达式

Java中使用正则表达式

String source = "Hello, This my phone number: 010-12345678. ";
String pattern = ".*(\\d{3}-\\d{8}).*";
Matcher matcher = Pattern.compile(pattern).matcher(source);while(matcher.find()){System.out.println(matcher.group());System.out.println(matcher.group(1));
}
复制代码

Kotlin中使用正则表达式:

val source = "Hello, This my phone number: 010-12345678. "
val pattern = """.*(\d{3}-\d{8}).*"""
val matcher = Pattern.compile(pattern).matcher(source)while (matcher.find()) {println(matcher.group())println(matcher.group(1))
}
复制代码

需要注意的是,Kotlin中有raw String,用三引号括起来。

也可以使用Kotlin提供的Regex类,写出更有Kotlin风格的代码:

val source = "Hello, This my phone number: 010-12345678. "
val pattern = """.*(\d{3}-\d{8}).*"""Regex(pattern).findAll(source).toList().flatMap(MatchResult::groupValues).forEach(::println)
复制代码

###集合框架

以List为例子,Kotlin中可以使用Java的集合框架:

val list = ArrayList<String>()//注意不同导包
list.add("haha")
list.removeAt(0)
复制代码

######Tips:Kotlin中对List进行了优化,比如添加了removeAt,实质上是映射了remove方法。

通过点击源码可以发现,ArrayList实际上是使用了Java的ArrayList:

@SinceKotlin("1.1") public typealias ArrayList<E> = java.util.ArrayList<E>
复制代码

Kotlin中可以通过xxxOf方法去创建集合,返回的是Kotlin内部定义的接口,是不可变的集合,并没有提供add等方法:

val list = listOf("1", "2", "3")
val map = mapOf("1" to "1","2" to "2","3" to "3")
复制代码

但是Java中访问这些集合的时候是当做普通的集合来使用的,因此操作的时候就会抛异常:

//Kotlin代码
object Test {val list = ArrayList<String>()
}//Java代码
List<String> list = Test.INSTANCE.getList();
list.add("1");
复制代码

程序运行不了,控制台输出:

Exception in thread "main" java.lang.UnsupportedOperationException: Operation is not supported for read-only collectionat kotlin.collections.EmptyList.add(Collections.kt)at com.nan.sam.SamJava.main(SamJava.java:24)
复制代码

###IO操作

以文件的读取为例子,先看看Java版本的:

BufferedReader bufferedReader = null;
try {bufferedReader = new BufferedReader(new FileReader((new File("build.gradle"))));String line;while ((line = bufferedReader.readLine()) != null) {System.out.println(line);}
} catch (Exception e) {e.printStackTrace();
} finally {try {if (bufferedReader!=null) {bufferedReader.close();}} catch (Exception e) {e.printStackTrace();}
}
复制代码

然后是Kotlin版本:

val bufferedReader = BufferedReader(FileReader(File("build.gradle")))
var line: Stringwhile (true) {line = bufferedReader.readLine() ?: breakprintln(line)
}bufferedReader.close()
复制代码

比较突出的不同点是,Kotlin中不能像Java一样“line = bufferedReader.readLine()”,line不会作为返回值。因此只能用传统的写法。

另外也可以通过use关键字进行简化:

val bufferedReader = BufferedReader(FileReader(File("build.gradle"))).use {var line: Stringwhile (true) {line = it.readLine() ?: breakprintln(line)}
}
复制代码

其中use是Closeable的一个扩展方法:

@InlineOnly
public inline fun <T : Closeable?, R> T.use(block: (T) -> R): R {var closed = falsetry {return block(this)} catch (e: Exception) {closed = truetry {this?.close()} catch (closeException: Exception) {}throw e} finally {if (!closed) {this?.close()}}
}
复制代码

最后,在读取这种小文件的时候,可以直接使用File的扩展方法:

File("build.gradle").readLines().forEach(::println)
复制代码

readLines的定义如下:

public fun File.readLines(charset: Charset = Charsets.UTF_8): List<String> {val result = ArrayList<String>()forEachLine(charset) { result.add(it); }return result
}public fun File.forEachLine(charset: Charset = Charsets.UTF_8, action: (line: String) -> Unit): Unit {// Note: close is called at forEachLineBufferedReader(InputStreamReader(FileInputStream(this), charset)).forEachLine(action)
}
复制代码

###装箱与拆箱

Java中有装箱与拆箱之分,例如int与Integer,但是Kotlin中统一用Int代替,一切的转换由编译器完成。

但是偶尔会遇到Java代码翻译成Kotlin代码的时候有歧义的情况,解决办法就是用Java代码去实现这个功能,而在Kotlin中使用。关于这类问题实际中遇到比较少,因此不仔细说明。

如果觉得我的文字对你有所帮助的话,欢迎关注我的公众号:

我的群欢迎大家进来探讨各种技术与非技术的话题,有兴趣的朋友们加我私人微信huannan88,我拉你进群交(♂)流(♀)

Kotlin 之旅8 Kotlin与Java共存相关推荐

  1. kotlin 调用java_从Kotlin调用Java代码

    Kotlin代码与Java代码完全兼容. Java代码在Kotlin代码中轻松调用,Kotlin代码也可以通过Java代码的正常方式调用. 从Kotlin调用Java代码 从Kotlin文件调用Jav ...

  2. Kotlin传递可变长参数给Java可变参数方法

    定义Java可变参数方法 package com.tcl.john.studymvvm.utils;/*** 调用Java方法的工具类* Created by ZhangJun on 2017/10/ ...

  3. 学习Kotlin(一)为什么使用Kotlin

    推荐阅读: 学习Kotlin(一)为什么使用Kotlin 学习Kotlin(二)基本语法 学习Kotlin(三)类和接口 学习Kotlin(四)对象与泛型 学习Kotlin(五)函数与Lambda表达 ...

  4. 手把手教你学Kotlin (1): JetBrains的Kotlin Educational Tool下载、安装和 Kotlin Koans的安装和使用

    文章目录 前言 1.Kotlin Educational Tool下载.安装 2.Kotlin Koans的安装和使用 前言 此教程面向没有Kotlin基础的程序员或者学生 1.Kotlin Educ ...

  5. 【Android NDK 开发】Kotlin 语言中使用 NDK ( 创建支持 Kotlin 的 NDK 项目 | Kotlin 语言中使用 NDK 要点 | 代码示例 )

    文章目录 一.创建支持 Kotlin 的 NDK 项目 二.Kotlin 语言中使用 NDK 要点 1.加载动态库 2.声明 ndk 方法 3.Project 下的 build.gradle 配置 4 ...

  6. 第3章 Kotlin语言基础 《Kotlin 极简教程》

    2019独角兽企业重金招聘Python工程师标准>>> 第3章 Kotlin语言基础 掌握基础,持续练习 学习任何东西,都是一个由表及里的过程.学习一门编程语言也一样.对于一门编程语 ...

  7. Kotlin入门(1)搭建Kotlin开发环境

    Kotlin做为一门编程语言,已经出现好几年了,但此前在国内并不闻名.自从5月份谷歌宣布它成为Android的官方开发语言之后,Kotlin猛然窜红了,虽说短期内Kotlin无法取代Java,但对于一 ...

  8. kotlin 扩展函数_在 Kotlin 中“实现”trait/类型类

    本文原发于我的个人博客:https://hltj.me/kotlin/2020/01/11/kotlin-trait-typeclass.html.本副本只用于知乎,禁止第三方转载. trait 与类 ...

  9. kotlin null_Kotlin Null安全– Kotlin可空

    kotlin null In this tutorial, we'll look into Kotlin Null Safety. NullPointerException is one of the ...

最新文章

  1. 百度编辑器(ueditor)上传图片
  2. 转载 React.createClass 对决 extends React.Component
  3. Spring4新特性——集成Bean Validation 1.1(JSR-349)到SpringMVC
  4. EBPY0106是什么意思
  5. linux下修改rm命令防止误删除
  6. 关于select中fd_set变量的一些通俗宏解释
  7. 【环境搭建001】ubuntu 和 win7 在vm 下的文件夹共享实践
  8. Octopress使用中经验总结
  9. wdcp v2.5.15 php版本,linux服务器/虚拟主机管理系统wdcp v2.5.6版本发布
  10. 用UltraISO制作CentOS的DVD光盘启动盘 安装系统
  11. vs2008 web创作组件安装失败
  12. CSS的border属性绘制简单三角形、边框三角形
  13. 如何成为靠谱的DotNet/C#程序员 (sunxiunan)(zz)
  14. aruba无线ap认证服务器,Aruba无线AP及AC配置.doc
  15. matlab angle函数
  16. SEOer未来发展的两个方向
  17. 为什么近视人群需要戴变色镜片?
  18. transform video to frames/提取视频中的每一帧
  19. 主谓宾定状补口诀及练习题
  20. 精品站长网交易系统源码/虚拟交易网站程序源码+全套打包2G

热门文章

  1. SecureCRT 8.0发布
  2. 新标签页打开链接_显示空白的问题!
  3. 用Python实现语音合成
  4. 基于BERT的数据库的问答系统
  5. 国内测试专业blog(部份),欢迎一起完善
  6. WPF 用户控件分享之边上带输入框的圆圈
  7. DDR信号完整性仿真介绍
  8. AllWinner T113 buildroot ssh连接功能
  9. python中lambda函数if用法-Python中关于Lambda函数的使用总结
  10. unix是计算机的操作系统,Unix属于计算机的哪种操作系统?