一、前沿

如果你学习过其他的编程语言,你就会发现 Java 的语法很是哆嗦,可是我们为什么没有放弃 Java 这门编程语言呢?因为 JVM 是一个非常好的平台,而且 Java 程序员目前在中国所占的比重实在是太高了。这是历史包袱导致的。暂且不说 Python,语法绝对比 Java 简化的不是一个级别,就连 C# 也比 Java 语法优美很多。

我们知道,Java 程序运行过程是这样的:

编写源代码(.java)-> 编译源文件(.class)-> JVM 虚拟机将 class 文件加载进内存,执行

既然如此,如果有一门语言同样能编译成 class 文件,再由 JVM 去加载他,并且这门语言比 Java 语法更加优美简洁,你乐不乐意去使用呢?那么这门优秀的语言就是 Kotlin。Kotlin 他的运程过程是这样的:

编写源代码(.kt)-> 编译源文件(.class)-> JVM 虚拟机将 class 文件加载进内存,执行。

2017年,Google 宣布 Kotlin 成为 Android 官方开发语言,可见Kotlin 之好。

当然,随着 Kotlin 的发展,Kotlin 已经不单单是 JVM 平台上的语言,也可以将 Kotlin 代码编译为 JavaScript,未来还会有 Kotlin Native,可见 Kotlin 绝对是极具潜力。

二、学习 Kotlin 前准备

工欲善其事,必先利其器。首先一定要选择一个好的 IDE,Kotlin 是由 JetBrains 公司开发,那么我们当然要用 JetBrains 公司自家的 IDE 啦,我们就选用 IDEA!相信现在绝大多数 Java 开发者都在用的。

我们新建一个普通项目即可。

如果我们要写 Kotlin 代码,很简单,右键,新建一个 Kotlin 文件即可。

新建文件后,IDE 会提示我们需要配置,按照提示,配置一下即可。

三、Kotlin 语法简介

如果你已经学习过了 Java,入门 Kotlin 会很快。

我们先来写一个Hello world!

打开我们新建好的 kt 文件,输入以下代码:

fun main(args: Array<String>) {    print("hello world")}

我们再来回顾一下 Java 代码:

class HelloWord{public static void main(String[] args){System.out.println("Hello world");     }}

我们对比一下,Kotlin 的代码非常少。我们 Java 中,方法必须写在类中,而我们的 Kotlin 支持包级函数,静态方法不需要写在一个类中。并且 Kotlin 每一句结束不需要分号。

在 Kotlin 中,所有变量声明都需要用 val 或 var 修饰,并且支持类型推断,但你需要注意的是,Kotlin 是一个静态语言。

变量声明格式 : val/var 变量名(:类型,可不写,会自动推断)

如 val i=1 和 val i:Int =1 的效果是一样的。

var i=1 和 val i=1 如果被翻译成 Java 分别就是:

final int i=1int i=1

被 val 修饰的变量编译后会被翻译成类似于 java 中的 final 关键字,这是 Kotlin 一大特点,在 Kotlin 中所有类,方法都会默认是 final 的。

小编这边建议您,初学的时候多看看 Kotlin 翻译成 Java 的字节码。 我们的 IDE 已经有相关插件了:

点击后会出现如图界面:

再点击红色框中的按钮,就会显示我们 Kotlin 被翻译成 Java 的代码了。

优秀的表达式

我们观察以下代码:

他和我们 Java 中的 if else 有哪些不同?

我们表达式也可以有返回值了,注意千万不要写 return xxx,因为 return 就跳出方法了。在 Kotlin 中,条件表达式的最后一句就可以作为返回值,这一个小技能可以说非常实用,类似的还有 try、catch 也有类似的功能。

加强版 switch

本人作为一名资深 Java 开发者,确很少用 switch,一来 switch 必须对相同类型进行操作,功能单一,可能还没有 if 强大,而且经常使用会增加代码耦合度,一般会使用多态结合相关的设计模式来代替。

我们来看看 Kotlin 中加强版的 switch 表达式 when:

当满足第一个 case 分支,就会结束这个表达式。同理,他也可能作为一个表达式,每一个分支最后一句可以返回一个值,再给一个变量去接收,是不是比 switch 强大了一万倍呢!

模板字符串

这个功能可是非常实用,我们在 java 中可能常常会有拼接字符串的痛苦,没事,Kotlin 可以解决你的这个痛苦,我们看看这个代码:

我们在字符串中,使用 ${},在花括号中,可以写 Java 代码,这样就达到了模板字符串的效果。当然你也可以这样这样做:

使用 $ 加上变量名可以直接输出这个变量。那么我们如果想输出 $,那么就需要转义了,和 Java 一样,使用 \。

包装类和基本数据类型不存在了

在 Java 中类似 int、double 等等所有基本数据类型都有其对应的包装类,在 Kotlin 中不存在了,一律使用 Int、Double、Float、String……

在编译的时候,Kotlin 会根据我们的情况智能选择基本数据类型还是包装类,不需要程序员去操心了。

data class,再见 Java bean

我们在写 JavaBean 一般过程是写上一个 class 类,里面编写若干个字段,然后给上若干个 get/set 方法,有时候还会重写 toString、equals、HashCode 方法。

这些过程其实也有些重复,如果我们使用 Kotlin 为我们提供的 data class 编写一个类:

data class Person(val username:String,val age:Int)

这样我们就写好了一个 data class,短短一句话,我们从声明也可以看出,我们给 Person 这个类定义了 username 和 age 两个属性,我们使用 IDEA 自带插件,把他翻译成 Java 代码看看:

public final class Person {    @NotNull    private final Stringusername;    private final int age;    @NotNull    public final String getUsername() {      return this.username;    }    public final int getAge() {      return this.age;    }    public Person(@NotNull String username, int age) {      Intrinsics.checkParameterIsNotNull(username, "username");      super();      this.username = username;      this.age = age;    }    @NotNull    public final String component1() {      return this.username;    }    public final int component2() {      return this.age;    }    @NotNull    public final Person copy(@NotNull String username, intage) {      Intrinsics.checkParameterIsNotNull(username, "username");      return new Person(username, age);    }    // $FF: synthetic method    // $FF: bridge method    @NotNull   public static Person copy$default(Person var0, String var1, int var2,int var3, Object var4) {      if ((var3 & 1) != 0) {         var1 = var0.username;      }       if ((var3 & 2) != 0) {         var2 = var0.age;      }       return var0.copy(var1, var2);    }    public String toString() {      return "Person(username=" + this.username + ", age=" + this.age + ")";    }    public int hashCode() {      return (this.username != null ? this.username.hashCode() : 0) * 31 + this.age;    }    public boolean equals(Object var1) {      if (this != var1) {         if (var1 instanceof Person) {            Person var2 = (Person)var1;            if (Intrinsics.areEqual(this.username, var2.username) && this.age == var2.age) {               return true;            }         }          return false;      } else {         return true;      }    } }

data class 太厉害了,Kotlin 在编译的时候会自动帮我们加上 get/set 方法,还会为我们加上 tostring、euqals、hashcode 方法。

不过,你要注意的是,Kotlin 类默认是 final 的,所以我的 data class 是不能被继承的,而且他没有无参的构造方法。如果这样直接使用 MyBatis 是会报这个类找不到无参构造方法的错的。

为了解决这些问题,Kotlin 官方推荐了 no-arg 插件来解决这一问题,如果你想让 data class 编译时候去掉 final 关键字,可以使用 Kotlin 官方插件 all-open 插件来解决这一问题。

插句题外话,在 Spring5 中,Spring 专门针对 Kotlin 做过很多的优化。比如,AOP 这一底层实现,相信有一定功底的人士都知道,spring 会为这个类使用 CGLIB 技术动态生成一个子类。而我们的 Kotlin 类默认是 final 的,因此,如果我们是用 Kotlin 写的 AOP,想让我们写的 AOP 类能正常运行,就必须在 class 前面加上 open。可每次写很麻烦,我们索引官方也推出了一个 kotlin-spring 插件,可以为这些类自动去 final 关键字。

空指针异常不存在了

Kotlin 中所有类型都区分非空或可空类型,比如可空的 Int,就是 Int?,如果这个类型允许空,我们就在这个类型后面加个 ?,不加 ? 的话则这个类型不可为空!

比如我们定义一个方法某一个参数类型后面我们就指定了 ?,我们可以传递 Null,反之则不可以,或者加上 ! 强制传递。

Kotlin 的绝技实在是太多了,包括还有定义方法的时候,我可以给参数指定默认值,调用的时候也可以指定参数名的时候进行传递,在编译时候,Kotlin 会生成若干个重载的 Java 方法。当然这只是九牛一毛,Kotlin 最强大的就是高阶函数和函数式编程了,并且支持科理化。支持运算符重载,可以为类增加扩展方法,强大到令人发指。

同时,Kotlin 还支持协和编程(目前这块不太成熟),由于篇幅有限,如果大家有兴趣,我可以再做一次专题讲解。

编写单例类

单例模式是 23 种设计模式中非常常用的设计模式之一。在 Kotlin 中也有提供我们非常快捷的方式编写单例类,实现单例仅仅只需要一行代码:

object Singleton

是的,你没有看错,只需要写2个单词 ,object 代表声明一个单例类,Singleton 为单例的类名,是不是很Easy?

我们测试一下:

这里补充一下,由于 Kotlin 支持运算符重载,在 Kotlin 中,双等号等同于调用 equals 方法,三等号才是比较内存地址。我们看到这里输出的是 true,则说明,输出的是同一个对象。我们再来看看他字节码,翻译成 Java 的代码:

可以看出,就是一个简单的单例模式。构造方法没有显示出来,其实是私有化的。其实我们还是可以通过反射去修改构造方法访问修饰符来破坏他的单例的。

扩展方法

相信如果你做过多年的 Java 开发,手头上一定有大量的 Util 类,比如 DateUtils、HtmlUtils、StringUtils 等等,其实这都是 Java 这门语言造成的,当你学会扩展方法后,从此告别 Util。

比如我们要判断一个字符串是否长度大于 0,我们无非要判断他不为 null,且长度大于 0,如果用 Java 去实现相信你一定会写一个 StringUtils,那么我们如何用 Kotlin 的扩展方法去实现呢?

我们为 String 扩展一个 isNullOrEmpty 方法,如何返回 false,则说明长度大于 0。

我们在定义方法的时候前面加上对应的类名即可变成扩展方法了。

fun String.isNullOrEmpty():Boolean{    return !(this!=null&& this.isNotEmpty())}

这个代码可以写在任何地方。

我们写测试类调用:

是不是很自然。向 Util 说再见吧!其实我们的 Kotlin 在 String 类,集合类,IO 类等 JDK 很多类都提供了大量的扩展方法,比如我们学一个文本文件,现在只需要一句话:

val file = System.IO.File("d:/1.txt")    println(file.readText())

readText 就是 Kotlin 为我们写的扩展方法,类似的其实还有很多。因此,使用 Kotlin 一定会大大提高你的工作效率。

运算符重载

在 Kotlin 中,每一个运行符对应一个该类中的方法,如果该类中有相应的方法实现,就可以进行运算符重载。

就连调用方法其实也是一样,比如我们调用 a(b),等同于 a.invoke(b):

表达式
            对应转换
        a + b
            a.plus(b)
        a - b
            a.minus(b)
        a * b
            a.times(b)
        a / b
            a.div(b)
        a % b
            a.mod(b)
        a..b
            a.rangeTo(b)
        a[i]
            a.get(i)
        a[i, j]
            a.get(i, j)
        a[i_1, …, i_n]
            a.get(i_1, … , i_n)
        a[i] = b
            a.set(i, b)
        a[i,j] =b
            a.set(i, j, b)
        a[i_1, … , i_n] = b
            a.set(i_1,… ,o_n,b)
        a in b
            b.contains(a)
        a !in b
            !b.contains(a)
        a[i]
            a.get(i)
        a[i, j]
            a.get(i, j)
        a[i_1, …, i_n]
            a.get(i_1, … , i_n)
        a[i] = b
            a.set(i, b)
        a[i,j] =b
            a.set(i, j, b)
        a[i_1, … , i_n] = b
            a.set(i_1,… ,o_n,b)
        
我们举个例子,假如我们要计算一个日期后的若干天,我们如果用 Java 去干,相信你一定要写不少于 10 行代码,而且会很痛苦。而在 Kotlin 中,有了运算符重载,我就有了一个很好的思路,让 data+1 就返回一天后的日期,是不是很绝?

说到做到,我们来实现:

根据上面表我们可以看出,+ 要重载的方法是 plus。可是 Date 类是 JDK 为我们提供的,我们如何去为他添加一个方法呢?没错,我们之前讲过,Kotlin 支持类的扩展方法,我们为 Date 类扩展一个 plus 方法,扩展方法和运算符重载结合起来也会被识别。

对了,重点还没有说,如何定义运算符重载呢?仅仅写对应的方法还不足够,还要在 fun 前面加上 operator 关键字。所以,我们写出如下代码:

operator fun Date.plus(nextVal:Int):Date{    val calendar = GregorianCalendar()    calendar.time = this    calendar.add(Calendar.DATE, nextVal)    return calendar.time}

为了方便查看日期字符串,我们再扩展一个 stringFormat 方法,由于"yyyy-MM-dd"格式太常用,我们再给他一个默认值。

fun Date.stringFormat(formatType:String = "yyyy-MM-dd"):String{    return SimpleDateFormat(formatType).format(this)}

写测试方法:

绝了,不得不感叹 Kotlin 的伟大!

四、Kotlin 与 Java 混合开发

由于 Kotlin 和 Java 编译成 class 文件后完成一样,所以 Kotlin 和 Java 有着天然的兼容性,100% 兼容。在 Kotlin 中你可以随意的去使用 JVM 中定义好的类,也可以是你自己写好的 Java 类,同一个项目中你可以既有 Java 类,也可以有 Kotlin 类。

比如你定义了一个 data class Person 类,在同一个项目中,你可以新建一个 Java 类,使用 Person person = new Person(“小明”,12); 这完全没有问题的。同样,你用 Kotlin 定义好的类,在 Java 中可以同样使用。所在,从现在开始使用 Kotlin,不要怕,即使有地方你担心 Kotlin 自己不熟悉而实现不了,那你也可以在这时候使用 Java 去实现。100% 兼容,Java 中的所有类库都可以去使用。

这里附上一张 Kotlin 使用 SSM 图:

可以看出,源码是 Kotlin 的,我们同样可以使用 Spring 框架,再附上这个项目源文件。

文件前面图标右下角带 K 的都是 Kotlin 文件,可见,Kotlin 和 Java 是非常好的。

那么,像扩展方法、运算符重载、默认参数这类的我们该用 Java 如何去调用呢?

这里有很遗憾了,由于 Java 语法的限制我们不能像 Kotlin 那样去使用,但这并不代表我们不能用 Java 去调用,我们在 Java 中,只能当成一个普通方法去使用了。

五、Kotlin 与 Java 总结

个人认为 Kotlin 取代 Java 只是时间问题,现如今 Java 的更新速度已经很缓慢了,已经有越来越多的 Java 开发者去转战 Kotlin 这门语言。即使你现在的项目已经用 Java 写的很多,从今天开始你也可以使用 Kotlin,与 Java 百分之一百兼容,这是他的最大的特点。在未来,Kotlin 也必定会走出 JVM 这个平台,准确说,现在已经迈出了,未来会越来越强大。

入门 Kotlin 和 Java 混合开发相关推荐

  1. Kotlin和Java混合开发总结(基于Kotlin1.3.0版本)

    我本来是不想学习kotlin的,但是现在的形势,很多公司都在使用kotlin开发,可以说学会kotlin也是无奈之举,既然是潮流,谷歌也在大力推广,所以还是只能硬着头皮逼迫自己学一下,也能更快适应公司 ...

  2. Kotlin和java混合开发

    Kotlin和java混合开发 kotlin继承Java的方法 调用java的方法,参数最好用可空类型,除非明确java的参数是非空 而java代码如果需要可空 可以通过@Nullable 需要不可空 ...

  3. kotlin与java混合开发_使用kotlin和Java混合开发Android项目爬坑记录

    使用kotlin和Java混合开发Android项目爬坑记录 不定期将开发过程中遇到的问题添加在此处,加深记忆. 主要内容包括但不限于java与kotlin语言的一些区别,以及在使用android-s ...

  4. 《Kotlin从小白到大牛》第21章:Kotlin与Java混合编程

    第21章 Kotlin与Java混合编程 Kotlin毕竟还是一种新的语言,所以很多项目.组件和框架还是用Java开发的,目前Kotlin不能完全取代Java,因此有时会使用Kotlin调用Java写 ...

  5. java scala 混合打包_scala和java混合开发打包

    如何进行scala和java混合开发打包? 首先创建maven工程,在pom.xml添加一下依赖 1.8 UTF-8 3.8.1 1.6.4 3.1 2.11.8 2.3.2 org.scala-la ...

  6. 《Springboot极简教程》Springboot使用Kotlin和Java混合编程

    配置 要想实现Springboot使用Kotlin和Java混合编程,需要使用kotlin插件: spring-boot-gradle-plugin kotlin-gradle-plugin 具体配置 ...

  7. Kotlin 为什么可以和Java混合开发

    学! 本文:https://www.jianshu.com/p/e3afe651052b 文章目录 前言 Kotlin 互操作性 总结 参考文献 前言 闲来无聊,和一个朋友聊天. 他突然问我:你知道K ...

  8. Java Web基础入门第九讲 Java Web开发入门——再探Tomcat服务器

    web应用程序 web应用程序指供浏览器访问的程序,通常也简称为web应用.例如有a.html.b.html--多个web资源,这多个web资源用于对外提供邮件服务,此时应把这多个web资源放在一个目 ...

  9. 超简单的混合开发入门 JS实现安卓Listview

    最近在开发一款报表引擎,里面就需要我会写js做一些简单的混合开发,刚开始学习混合开发的前两天是最郁闷的,毕竟这是一门新的语言,但是还是硬着头皮往上搞了,到第二天的时候就把支持懒加载的Listview倒 ...

最新文章

  1. 深度学习 英文 训练阶段_半监督深度学习训练和实现小Tricks
  2. Spring Boot中使用时序数据库InfluxDB
  3. 解密亚洲诚信如何做到HTTPS的最佳安全实践
  4. 8086实时时钟实验(二)——《x86汇编语言:从实模式到保护模式》读书笔记06
  5. java什么是网络接口_java接口和类的区别是什么?它们都有哪些作用呢?
  6. 书呆子rico_寻找设计和类型书呆子的清道夫
  7. python随机生成验证码_Python生成随机验证码的两种方法
  8. easyUI的使用.datagrid()生成列表日期时间显示异常,一个方法带入有效修复
  9. visio 连接线样式设置 如箭头线
  10. 2021年中国茶叶电商发展现状及未来发展趋势分析[图]
  11. 安卓平板微信和手机微信同时登陆_如何查看手机上的微信登陆记录
  12. 美团饿了吗CPS红包,别人领红包下单,你拿推广佣金(附源码)
  13. 【Python实用工具】暴力破解-2!Python编写八位数密码本
  14. 京东店铺所有商品API接口(整店商品查询API接口),京东店铺商品API接口
  15. 转载精品:工作8年的普通专科生程序员的一些感悟
  16. 音乐社会计算机英语,计算机音乐技术应用,Computer music technology application,音标,读音,翻译,英文例句,英语词典...
  17. os-level版本控制工具
  18. 解决org.springframework.beans.factory.NoUniqueBeanDefinitionException No qualifying bean of type
  19. 局域网使用kubeadm安装高可用k8s集群
  20. asp.net 中根据sessionid 获取或删除session

热门文章

  1. intel fpga 开发工具Quartus Prime 软件的安装,使用详细教程
  2. 做机器人,必过的一道坎!
  3. 一根网线有这么多“花样”,你知道吗?
  4. 过滤器用到了java哪个模式_设计模式之过滤器模式——Java语言描述
  5. wordpress程序安装php多少,2020最新WordPress网站程序详细安装教程
  6. mysql udf编译_MySql UDF 调用外部程序和系统命令
  7. soundbar未来发展_智能电视时代 Soundbar未来发展之路
  8. tps协议和onvif协议_做监控的你,应该了解的ONVIF协议!
  9. python的类包括_Python的类,复杂吗
  10. ECMS系统服务器死机的处理,内存问题服务器死机一例