Kotlin杂谈系列十二

  • 这次就主要来谈谈kotlin和java互操作的问题

  • kotlin出来的使命就是为了解决java的模板问题和一些冗长的问题所以kotlin天生就很好的支持了java 所以我们在java代码中可以很好的引用java的类库和代码 但是在java中调用kotlin的代码就没那么容易了

  • 首先讲讲编译过程,如果一个项目里有kotlin代码和java代码那么编译时 kotlin编译器会先为java代码存根来支持他们之间的依赖 然后在使用java编译器这样就能运行了 因为kotlin代码和java代码在字节码层面上是没有差异的

  • 首先是静态方法

    我们知道在kotlin中是没有静态的方法的 在kotlin来表示类级别的是伴生对象 所以我们可以在伴生对象的方法上加上注解 @JvmStatic 这样的意义在于可以让java以静态代码的格式来调用伴生队象的方法 但是实质一个实例方法

//java文件
public class Test {public static void main(String[] args) {Book.Companion.hi();//这里}}//kotlin文件
class Book {companion object{fun hi(){println("I am a book")}}
}
  • 可以看见如果不用**@JvmStatic** 修饰的话就会多一个中间变量来桥接Companion 这个是当伴生对象没有名字的时候 有名字的时候就是那个名字
//java文件
public class Test {public static void main(String[] args) {Book.show.hi();//这里}}//kotlin文件
class Book {companion object show /*这里哦 指定了名字*/{fun hi(){println("I am a book")}}
}
  • 现在来看看 @JVMStatic的威力吧
//java文件
public class Test {public static void main(String[] args) {Book.hi();/*这里*/}
}//kotlin文件
class Book {companion object show{@JvmStatic/*这里*/fun hi(){println("I am a book")}}
}
  • 就这样就可以让java调用kotlin的伴生对象方法象静态方法一样但是实质不一样 来看看反编译的源码吧

public final class Book {@NotNull//单例模式public static final Book.show show = new Book.show((DefaultConstructorMarker)null);
/*-----------------------重点-----------------------------------*/@JvmStatic /*外部类的桥接方法*/public static final void hi() {show.hi();}public static final class show {@JvmStatic/*真正的实现逻辑*/
/*-----------------------重点-----------------------------------*/public final void hi() {String var1 = "I am a book";System.out.println(var1);}//构造器私有化private show() {}// $FF: synthetic methodpublic show(DefaultConstructorMarker $constructor_marker) {this();}}
}
  • 可以看见hi()方法并为变成真正的静态方法而是在外部类又包装了一个静态的方法 但是具体的逻辑还是在内部类的hi()方法

  • Kotlin 重载运算符

相信用过都说好 ,但是java并不支持所以怎么办呢 如果kotlin实现了运算符重载,那java只能调用对应方法了 例如 + --> plus()

//java 代码
public class Test {public static void main(String[] args) {new Book().plus(new Book());}
}//kotlin代码
class Book {operator fun plus(book : Book){println("add a book price")}
}
  • 访问属性

kotlin当我们访问属性的时候 实际上是访问了我们的getter / setter 但是java没有这么智能就只能手动调用getter / setter

//java代码
public class Test {public static void main(String[] args) {Book book = new Book();System.out.println(book.getName());}
}//kotlin代码
class Book {val name = "Kotlin VS Java"
}
  • 因为他是val变量所以只有getter方法

  • 传递lambda

java中的lambda必须是个接口 而kotlin的lambda实质上是一个匿名函数

所以传递时 就的导kotlin中的Function<T>等类似的包

//java代码
public class Test {public static void main(String[] args) {Book book = new Book();book.ok(/*传入的lambda表达式*/() -> {System.out.println("加油");return null;});}}//kotlin代码
class Book {fun ok (arg : () -> Unit){arg()}
}
  • 可以看到不能取消括号 参数写在外面

  • 异常

  • kotlin中全部都是未检查的异常(运行时异常) 而java中有已检查异常(编译时异常) 和 未检查异常 如果是已检查的异常就必须处理 (抛出 / 捕获)

看下面的代码

//java
public class Test {public static void main(String[] args) {Book book = new Book();try {book.getContent();} catch (java.io.FileNotFoundException ex) {System.out.println("not found");}}
}//kotlin
class Book {//这里@Throws(java.io.FileNotFoundException::class)fun getContent(){val bytes = java.io.File("aha").readLines()}
}
  • 在java中java.io.FileNotFoundException 是一个编译时异常 所以如果我们在kotlin中可以不处理但是java用的时候必须处理 所以利用注解 @Throws(java.io.FileNotFoundException::class) 抛出这个异常 这样java才能捕获到 否则就捕获不到 会在编译时抛异常 Exception ‘java.io.FileNotFoundException’ is never thrown in the corresponding try block

  • 带默认参数的函数

java中是没有带默认参数的函数这个特性的 那该怎么实现呢 哈哈 当然是重载

public class Test {public static void main(String[] args) {Book book = new Book();book.getPrice();// 'getPrice(int)' in 'Book' cannot be applied to '()'}
}//kotlin 代码
class Book {fun getPrice(price : Int = 1){println(price*2)}
}
  • 可以看到说没有找到这个方法签名但是加上一个注解就可以了 @JvmOverloads
//java 代码
public class Test {public static void main(String[] args) {Book book = new Book();book.getPrice();// 'getPrice(int)' in 'Book' cannot be applied to '()'}
}//kotlin 代码
class Book {@JvmOverloadsfun getPrice(price : Int = 1){println(price*2)}
}
  • 但是是有弊端的,我们知道java的重载是有以方法签名识别不同的重载的方法的

    看下面的代码

class Book {@JvmOverloadsfun getPrice(price : Int = 1,factor : Int = 2){println(price*factor)}
}//看看反编译的代码
public final class Book {//1.重载方法@JvmOverloadspublic final void getPrice(int price, int factor) {int var3 = price * factor;System.out.println(var3);}//2.重载方法@JvmOverloadspublic final void getPrice(int price) {getPrice$default(this, price, 0, 2, (Object)null);}//3.重载方法@JvmOverloadspublic final void getPrice() {getPrice$default(this, 0, 0, 3, (Object)null);}// $FF: synthetic methodpublic static void getPrice$default(Book var0, int var1, int var2, int var3, Object var4) {if ((var3 & 1) != 0) {var1 = 1;}if ((var3 & 2) != 0) {var2 = 2;}var0.getPrice(var1, var2);}
}
  • 这里重载的的一个参数的函数的参数 是 price 但是我们可以在kotlin中为factor利用命名参数的方式调用 但是java就肯定不行了 不能只想更改factor的值而不动price的值 这就是有点不完美性

  • 访问顶级的函数

    在字节码的层面 顶级函数会被封装在一个类里 这个类是文件名KT

//kotlin代码
//文件名 : Async01.kt
fun getPop(){println("hello")
}//反编译后
public final class Async01Kt {public static final void getPop() {String var0 = "hello";System.out.println(var0);}
}
  • 但是可以利用注解来指定类名 @file : JvmName()
@file:JvmName("async02")//这里
fun getPop(){println("hello")
}@JvmName(name = "async02"
)
public final class async02/*这里*/ {public static final void getPop() {String var0 = "hello";System.out.println(var0);}
}
  • 当然还有在Kotlin中还有很多的注解都是为了解决java和Kotlin的互操作的问题

  • 可以使用 Synchronized 来注解一个方法变成一个synchronized 标记的方法

  • 更多的注解可以看官方的文档

今天就是简单的了解一下kotlin和java的互操作

kotlin杂谈系列十二(Kotlin和Java的互操作)相关推荐

  1. kotlin杂谈系列六

    Kotlin杂谈系列六 从现在开始让我们一起遨游在函数式编程的海洋里吧 在将函数式风格的时候 就得想唠唠 命令式风格 和 声明式风格了 命令式风格 : 就是告诉计算机的具体步骤 和 具体实现 声明式风 ...

  2. Alamofire源码解读系列(十二)之请求(Request)

    本篇是Alamofire中的请求抽象层的讲解 前言 在Alamofire中,围绕着Request,设计了很多额外的特性,这也恰恰表明,Request是所有请求的基础部分和发起点.这无疑给我们一个Req ...

  3. Reflex WMS入门系列十二:Reflex里的Location

    Reflex WMS入门系列十二:Reflex里的Location 玩过SAP系统里的人都知道,在SAP系统里库存管理分为IM Level和WM Level.IM Level的仓库,在SAP里被定义为 ...

  4. Highcharts翻译系列十二:gauge测量图

    Highcharts翻译系列十二:gauge测量图 说明 测量图需要highcharts-more.js的支持 属性 参数 描述 默认值 animation 动画 true color 主要颜色或序列 ...

  5. xen是服务器虚拟化,xen虚拟化实战系列(十二)之xen虚拟机高可用之在线迁移

    xen虚拟化实战系列文章列表 xen虚拟化实战系列(十三)之xen虚拟机集中管理之convirt 1. 方案背景概述 本文是有对我们一个xen虚拟化生产环境将要改造的一个方案而来,在项目上线初期,没有 ...

  6. Web 前端开发精华文章推荐(jQuery、HTML5、CSS3)【系列十二】

    2012年12月12日,[<Web 前端开发人员和设计师必读文章>系列十二]和大家见面了.梦想天空博客关注 前端开发 技术,分享各种增强网站用户体验的 jQuery 插件,展示前沿的 HT ...

  7. java死锁业务场景_【深入浅出多线程系列十二】:什么是死锁?(场景+代码示例)...

    在学习Java的道路上,是否路过多线程时总让你很迷惘:很不巧,我也是,而使我们感到很迷惘主要原因都源于没有对概念的深深的理解和实践.所以我决定漫步Java多线程,同你一起会会多线程. 多线程系列 多线 ...

  8. Start Developing iOS Apps Today系列(十二)

    2019独角兽企业重金招聘Python工程师标准>>> Start Developing iOS Apps Today系列之后续 十二.iOS 技术 之前您已了解了如何编写一个具有简 ...

  9. 四十二、深入Java中的文件读取操作

    @Author:Runsen @Date:2020/6/8 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件.导致翘课严重,专业排名 ...

最新文章

  1. AdventureWorksBI.msi 和 AdventureWorksDB.msi 的官方下载地址及安装方法
  2. QualityCenter的备份
  3. javascript中常用数组函数
  4. Linux学习:目录遍历函数
  5. .Net连接Sybase数据库的几种方法[转]
  6. java:Eclipse:Juno:设置workspace路径
  7. 干货下载:可能是你见过的最全的网络爬虫总结
  8. Android真机没有sqlite3数据库的解决办法
  9. app.use(express.static)设置静态文件目录小解
  10. 对称加密之AES算法的python实现
  11. 操作系统之三种进程通信方式
  12. 支付宝支付模块-社区分享-接口样例-常见问题帖
  13. yum安装报错No package xxx available
  14. 计算机鼠标左键不起作用,电脑鼠标左键突然不好用了 右键没问题
  15. 镁光闪存颗粒对照表_海力士、南亚、镁光内存颗粒编码解析,妈妈再也不用担心你买内存条了...
  16. matlab半小提琴图,不会编程,也可以画小提琴图啦!
  17. qq大学认证如何修改随意修改认证内容
  18. POJ 1111(单身快乐)
  19. 使用无界面方式登录人人网
  20. 计算机网络和http权威指南 读书笔记

热门文章

  1. 思科服务器网关配置文件,思科服务器网关配置文件
  2. mysql之第n高的薪水
  3. SSL网站安全证书https加密防劫持
  4. css实现图片自动渐变切换、element-plus 的修改el-table的(边框线为虚线、表头样式)
  5. 最热门的10个美食公众号推荐
  6. 回溯算法——我欲修仙(功法篇)
  7. 蓝天格锐生命环的使用方法
  8. 大V科技谈 | VMware利用先进的自动化技术,简化混合办公模式
  9. 速卖通商品详情API接口(商品详情页面数据接口)
  10. python的数据与matlab互通:SciPy