Kotlin 和 java 都是一种静态类型的编程语言。表达式的类型在编译期已经确定,编译期能验证对象是否包含想访问方法或是字段,维护正确性与性能的同时保持源代码的简洁
 
    静态类型的优点:
  • 性能——方法调用速度更快,因为不需要在运行时才来判断调用的哪个方法
  • 可靠性——编译器验证了程序的正确性,因而运行时崩溃的概率更低
  • 可维护性——抹身代码更容易维护,因为你可以看到代码中用到的对象的类型
  • 工具支持——静态类型使IDE能提供可靠的重构,精确的代码补全特性
 
    ps:动态类型 编程语言:Groovy、Ruby
        允许定义可以存储任何数据类型的变量,或者返回任何数据类型的函数,并在运行时才解析方法和字段引用。
  • 优点:减少代码量增加创建数据结构的灵活性
  • 缺陷:在编译期不能通过编译期发现拼写类错误,继而导致在运行时出现错误
 
Kotlin 的特点
    一门务实、简洁、安全的语言,专注于互操作性。
 
Kotlin 语言的优势
  • 1、简洁
        相对于Android、java会减少很多代码;可以通过类型推导的方式判断对象的数据类型
  • 2、安全
        kotlin是空安全的处理的,在编译期就处理了各种null的情况避免空指针时出现在运行时,通过“?”字符
        kotlin在类型转换的时候会将检查和转换被组合成一次操作,一旦检查过类型,就不需要额外的转换就能直接引用属于这类的成员
  • 3、扩展函数
        即使没有权限去访问某个类,也可以扩展这个类的更多特性
  • 4、函数式编程
        kotlin也是基于面向对象的语言。通过lambda表达式,高阶函数等方式更方便的解决问题
  • 5、高度互操作性
        可以继续使用java的代码,比如java方法,继承java类,实现java接口及注解和依赖库,或是混合kotlin和java两种语言混合编写
 
 函数式编程
    (1)头等函数
            把函数(一部分行为)当作值使用,可以用变量保存它,把它当作参数传递,或者当作其他函数的返回值
    (2)不可变性
            使用不可变对象,这保证了它们的状态在其创建之后不能再变化
    (3)无副作用
            使用的是纯函数。此类函数在输入相同时会产生同样的结果,并且不会修改其他对象的状态,也不和其他交互
    (4)多线程安全
            多线程程序中最大的错误来源之一就是,在没有采用适当同步机制的情况下,在不同的线程上修改同一份数据。假如使用了不可变数据结构和纯函数,就能在一定程度上保证这样不安全的修改根本不会发生了
    (5)易于测试
            没有副作用的函数,可以独立地进行测试,不需要其他繁杂的代码来支撑整个环境
 
Kotlin 编译代码
    kotlin编译期会通过代码生成对应.class文件,并通过正在处理的应用程序类型的标准过程打包和执行生成的.class文件
通过命令行编译代码:
    kotlin <source file or directory> -include -runtime -d <jar name> java -jar <jar name>
 
Kotlin 编译器
    IntelliJ IDEA 和 Android Studio 之外还有在线网页编译器 http://try.kotl.in 在线playground 进行小代码示例,但是需要vpn!!
gradle添加依赖:
    在app的gradle下加入如下代码
apply plugin: 'kotlin-android'
 
apply plugin: 'kotlin-android-extensions'
在总工程project的gradle下加入如下代码:(大部分是自动生成的)
buildscript{
    ext.kotlin_version=‘1.2.60'
    ext.dagger_version=‘2.9’ //dagger2版本
    repositories{
        google() or mavenCentral()
        jcenter()
    }
dependencies {
        classpath 'com.android.tools.build:gradle:3.3.0-alpha03'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
 
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.60” -版本注意
 
    注意:java代码可以直接复制到kotlin类中进行自动转换为对应的kotlin代码;或是通过 Convert java File 头Kotlin File 动作进行转换整个文件
say many words, 那Kotlin现阶段的缺点呢?
Kotlin 的缺点
    1、没有命名空间
    kotlin允许在文件中定义顶级的函数和属性,但是会引起所有从kotlin引用的顶级声明无法区分的问题。会给理解代码的时候带来一定的难度。
例如,你定义这样一个顶级函数:
fun foo() {...}
你可以通过 foo() 调用。
如果你在不同的包里面也存在同样的方法,在调用时就不能明显区分出是调用的哪个方法。你可以通过在前面添加包名的方式去调用,但是如果 Java 约定的包名很深,似乎不太友好。
一种近似的解决方案是使用单例的 object 类。
object FooActions { fun foo() {...}}
这样你在 Kotlin 中可以通过 FooActions.foo() 调用,但是在 Java 中你必须要这样 FooActions.INSTANCE.foo()这样调用,这看起来很麻烦。
你也可以使用 @JvmStatic 去注解该方法,从而省掉INSTANCE。
  2、没有静态修饰符
2. 没有静态修饰符
Kotlin为静态函数和属性提供了一个和 Java 不一样的处理方式。并不是说有多烂,只是觉得让代码变得不干净而且没有必要。
例如,在 Android 的 View 类中定义的静态属性 View.VISIBLE 和静态函数 View.inflate
public class View { 
  public static final int VISIBLE = 0x00000000; 
  public static final int INVISIBLE = 0x00000004;
  public static View inflate(Context context, int resource) {...}
}
这个定义是简单的。然而,在 Kotlin 代码中:
class View { 
  companion object { 
    @JvmField 
    val VISIBLE: Int = 0x00000000 
    @JvmField 
    val INVISIBLE: Int = 0x00000004 
    @JvmStatic 
    fun inflate(context: Context, resource: Int) {...} 
  }
}
注:companion object为伴生对象
尽管 Kotlin 的版本并没有那么恐怖,但是它的复杂程度超过了我对这门语言的预期。如果去掉注解,你在 Java 中就不得不使用这样可怕的语法去调用:
// With annotations:
View.VISIBLE;
//Without annotations:
3. 编译方法数量
Kotlin 肯定会减少项目中的代码行数,但是它也会提高代码在编译以后的方法数。主要原因就是 Kotlin 属性的实现方式。
和 Java 不一样,Kotlin 没有提供单独定义域的方式。你必须使用 val 或者 var 来声明变量。这样有一个好处,就是省去了像 Java 一样定义 getters 和 setters 方法。
但是这需要一定的成本。每一个public的 val 变量都会生成一个「支持域」和一个能被 Java 调用的 getter 方法。每一个public的 var 变量都会生成 getter 和 setter 方法。
// kt 文件:
// 默认就是public,无需额外添加public修饰符
val strValPublic: String = "strValPublic"
var strVarPublic: String = "strVarPublic"
 
// 以下是反编译结果:
public final class VarAndValKt {
   @NotNull
   private static final String strValPublic = "strValPublic";
   @NotNull
   private static String strVarPublic = "strVarPublic";
 
   @NotNull
   public static final String getStrValPublic() {
      return strValPublic;
   }
 
   @NotNull
   public static final String getStrVarPublic() {
      return strVarPublic;
   }
 
   public static final void setStrVarPublic(@NotNull String var0) {
      Intrinsics.checkParameterIsNotNull(var0, "<set-?>");
      strVarPublic = var0;
   }
}
拓展:Intrinsics.checkParameterIsNotNull 方法其实很简单,原理:
public static void checkParameterIsNotNull(Object value, String paramName) {
    if (value == null) {
        throwParameterIsNullException(paramName);
    }
}
其实所有空安全的秘密都在这个类里面了
庆幸的是,私有属性的 getters 和 setters 会生成域而不是生成方法。
// kt文件:
private val strValPrivate: String = "strValPrivate"
private var strVarPrivate: String = "strVarPrivate"
 
// 以下是反编译结果:
public final class VarAndValKt {
   private static final String strValPrivate = "strValPrivate";
   private static String strVarPrivate = "strVarPrivate";
}
所以如果你把项目中Java代码转成Kotlin,而且之前的 Java 代码中定义了大量的公开域(这在定义常量的时候很常见),你会惊奇的发现最终编译生成的方法数量大幅上升。
如果你的 Android 应用快接近方法数限制了,我建议你为不需要自定义 getter 方法的常量加上 @JvmField 注解。这样会阻止 getters 方法的生成,从而减少你的方法数。
// kt 文件:
@JvmField
val strValPublic: String = "strValPublic"
@JvmField
var strVarPublic: String = "strVarPublic"
 
// 以下是反编译结果:
// 注意看,get set方法消失,取而代之的是private修饰符变成了public
public final class VarAndValKt {
   @JvmField
   @NotNull
   public static final String strValPublic = "strValPublic";
   @JvmField
   @NotNull
   public static String strVarPublic = "strVarPublic";
}
 

数据类型

数字

类型 宽度
Double 64
Float 32
Long 64
Int 32
Short 16
Byte 8

Char 类型

Kotlin 中字符类型为 “Char”,和 Java 中不同的是,Kotlin 中的 Char 类型无法作为数字使用。如果需要将 Char 类型转换为 Int 类型,则可以直接调用"toInt" 方法。

Boolean 类型

Kotlin 中的 Boolean 类型和 Java 中的一样,只有两个值true 和 false

数据类型的表示方式

  • 字面常量十进制表示:1234,1234L(Long 类型)
  • 十六进制表示:0x1234ABCD
  • 二进制表示:0b00100010
  • 不存在八进制表示
  • Double 类型:123.45,123.45e10
  • Float 类型:123.45F/f
  • 使用"_"让数字更加易读
    • 1234_5678_9L
    • 0x12_34_56_78_AB
    • 0b11010010_01101001_10010100_10010010

变量的初始化

在 Kotlin 中存在有 2 种变量 var 和 val。其中 var 表示的是“通常的变量”,val 则表示的是“不可变变量”,这可以类比 Java 中的 final 修饰的数据类型类型。

一切皆对象,所以不管是var还是val变量,都存在成员函数。而val变量不可变的本质就是它不存在 set 方法。所以,可以使用 var 去覆盖一个 val ,但是无法反过来为之。

Kotlin 中变量的初始化语句为:

val/var 变量名 : 变量类型 = 值,其中变量类型是可选的

需要注意的是,在 Kotlin 中不允许声明了一个变量但是却不去初始化它。

在 Kotlin 中,数据有以下的几种初始化方法:

val a :Int = 1 // 对变量 a 立即赋值
val b = 2 // 因为很容易推断出 b 的类型是 Int,所以变量类型可以省略,这种初始化方式后面使用时变量不可赋值为空
val b ?= null // 将 b 的值设置为 null(需要注意 Kotlin 是空类型安全的,每次使用之前需要判断是否为空)
val c = null!! // 将 b 的值强制设置为 null,则之后的代码不再做是否为空的安全检查
b.toLong // 会报错
c.toLong // 不会报错

运算符

隐式类型转换

因为表示的方法不同,较小类型的数据无法隐式转换为较大类型的数据。也就是说,无法在不同类型之间比较两个变量是否在“数值”上是否相等。另外,也不可以将较小类型的数据隐式赋值给较大的数据类型:

val a : Int ?= 1
val b : Long ?= 1
print(a == b) // 这里会产生一个错误, Int 类型和 Long 类型无法进行比较
/****************************************************************/
val a : Byte = 1
val b : Int = a // 错误,小的数据类型无法隐式装箱为大的数据类型,如果需要赋值应该写作: = a.toInt()

Boolean 类型的布尔运算

  • || :短路逻辑或运算
  • &&:短路逻辑与运算
  • !:短路逻辑非运算

字符串

在 Kotlin 中字符串使用 String 类型进行表示。字符串是不可变的。字符串默认拥有迭代器,可以使用 foreach 进行遍历。

和 Java 中的字符串有一处显然的不同点,那就是 Kotlin 中的字符串除了拥有转义字符的赋值方式外,还存在类似于 Python 中那种通过三个引号进行的赋值方法,其中被三个引号括起来的所有文字,都是所见即所得的。

val text = """
for (c in "foo")
print(c)
"""

在这种字符串的赋值方式中,还有一种方法,用于去除前导空格。

val text = """
|Tell me and I forget.
|Teach me and I remember.
|Involve me and I learn.
|(Benjamin Franklin)
""".trimMargin()

在上面的例子中,默认使用"|"作为边界的前缀,如果想要使用其他的符号作为前缀,则将对应符号的字符作为传输传递入 trimMargin 函数。

字符串模板

Kotlin 的字符串应该吸收了很多脚本语言的字符串处理特性。它可以包含有模板表达式。所谓的模板表达式,你可以将其看作是很短的一小段代码。模板表达式由 $ 符号开头,后面紧跟随一个名称。这里的名称可以是某一个变量名。如果需要执行一些比较复杂的表达式,则使用花括号将表达式扩起来共同作为一个名称。

val strA : String = "abcd"
val strB = "$strA.length is ${s.length}" // abcd.length is 4

流程控制

条件语句

条件语句的形式为:if (condition) statement。作为扩展,还有 if ... else语句和多个 if 语句嵌套。

fun max(){
val a = 1
val b = 2
if (a > b) {
retrun a
}else{
return b
}
}

和 Java 中有点不同的是,if 中的分支可以是代码块,最后的一个表达式就作为该块的值。那么,上面的例子就可以写作:

fun man(){
val a = 1
val b = 2
if (a > b){
a
}else{
b
}
}

另外,if语句还可以作为表达式使用:

val max = if (a > b) a else b

在上述语句中,变量 max 的值最终是多少,需要看变量 a 和 b 的最终结果。

条件判断中的范围判断

在传统的 C 语言或者是一些其他的类似 C 的语言中,如果想要判断一个数是否在一个区间内,可能需要那么写:

if (i >= 5 && i <= 10) {
// do something
}

而在 Kotlin 中这一切就简化了许多:

if (i in 5..10) {
// do something
}

另外还有:

if (i !in 5..10) { if (!(i >= 5 && i <= 10))
// do something
}

循环语句

for 循环

需要注意的是,在 Kotlin 中,不支持那种 C 中的传统 for 循环。

使用迭代器

val items = lostOf("apple","banana","kiwi")
for (item in items) {
println(item)
}

使用索引

val items = lostOf("apple","banana","kiwi")
for (index in items.indices) {
println(${items[index]})
}

虽然不具备类似于 C 中那样的 for 循环,但是并不意味着 Kotlin 不可以实现那种需求:

for (i in 1..5) {   // for (int i = 1;i <= 5;i++) {print(i)}
print(i) // 12345
}

需要注意的是,这里的 1..5 左右都是闭区间的。

for (i in 5..1) {
print(i) // 错误,没有任何输出
}

类似上面代码展示的这样,是无法进行输出的。如果想要逆序输出,那么你需要使用函数downTo 替代..

for (i in 5 downTo 1) {
print(i) // 54321
}

以上的例子都是针对步长是1的情况,如果实际的步长不是1,那么需要使用 step 函数来指定步长:

for (i in 1..5 step 2) {
print(i) //1 3 5
}

另外,又有一些时候(大部分的时候)可能并不需要包括结束区间。那么,这时候需要使用到 until 函数来替代 ..

for (i in 1 until 5) {
print(i) // 1234
}

while 循环

同类 C 语言。

do...while 循环

同类 C 语言。

多重选择 (when)

Kotlin 中不存在 switch...case...这样的表达式,取而代之的是 when 语句。

最简的 when 语句如下:

when (x) {
1 -> print(1)
2 -> print(2)
else ->print("null")
}

其中的 x 的值将会作为判断的条件,此 when 语句会逐一比对条件,如果找到任一匹配的条件,则执行->之后的语句块然后退出。假如所有的条件都不匹配,则会执行else对应的语句块。

和之前的if语句一样,when语句可以作为单独的表达式使用,也可以作为一个语句使用。如果它作为表达式使用,则对应块的值会作为此 when 的值,而每一个语句块的值是由该块最后一条语句所决定的。另外就是如果作为语句使用,则必须包含有 else,除非编译器能够确定每一个分支都已经覆盖到了(比如对于 Boolean 类型,则条件应该是 true 和 false,如果已经包含了这 2 个分支,则可以不需要 else。当然,随手添加一个 else 语句并不是什么坏习惯)。

相对于传统的类 C 语言,when 语句的条件要宽松很多。除了是一个固定的值,还可以是表达式:

when (x) {
parseInt(s) -> print("s encodes x")
else -> print("s does not encode x")
}
////////////////////////////////////////////
when (x) {
in 1..10 -> print("x is in the range")
in validNumbers -> print("x is valid")
!in 10..20 -> print("x is outside the range")
else -> print("none of the above")
}

Kotlin基础学习的更多相关文章

  1. Kotlin基础学习笔记(2)

    1.基本数据类型 Kotlin的基本数值类型包括byte,short,int,long,float,double等.字符不属于数值类型,是一个独立的数据类型. 数字类型中不会主动转换.例如,不能给Do ...

  2. Kotlin基础篇(一)

    写在前面: 因为工作需要,目前转安卓开发,用的IDE是AS3.2版本,语言的话,用的是Kotlin.由于之前是做.NET的,没接触过这方面的东西,所以完全是小白一枚.所以想着开个博客,以此来记录自己的 ...

  3. salesforce 零基础学习(五十二)Trigger使用篇(二)

    第十七篇的Trigger用法为通过Handler方式实现Trigger的封装,此种好处是一个Handler对应一个sObject,使本该在Trigger中写的代码分到Handler中,代码更加清晰. ...

  4. 如何从零基础学习VR

    转载请声明转载地址:http://www.cnblogs.com/Rodolfo/,违者必究. 近期很多搞技术的朋友问我,如何步入VR的圈子?如何从零基础系统性的学习VR技术? 本人将于2017年1月 ...

  5. IOS基础学习-2: UIButton

    IOS基础学习-2: UIButton   UIButton是一个标准的UIControl控件,UIKit提供了一组控件:UISwitch开关.UIButton按钮.UISegmentedContro ...

  6. HTML5零基础学习Web前端需要知道哪些?

    HTML零基础学习Web前端网页制作,首先是要掌握一些常用标签的使用和他们的各个属性,常用的标签我总结了一下有以下这些: html:页面的根元素. head:页面的头部标签,是所有头部元素的容器. b ...

  7. python入门到精通[三]:基础学习(2)

    摘要:Python基础学习:列表.元组.字典.函数.序列化.正则.模块. 上一节学习了字符串.流程控制.文件及目录操作,这节介绍下列表.元组.字典.函数.序列化.正则.模块. 1.列表 python中 ...

  8. python入门到精通[二]:基础学习(1)

    摘要:Python基础学习: 注释.字符串操作.用户交互.流程控制.导入模块.文件操作.目录操作. 上一节讲了分别在windows下和linux下的环境配置,这节以linux为例学习基本语法.代码部分 ...

  9. CSS零基础学习笔记.

    酸菜记 之 CSS的零基础. 这篇是我自己从零基础学习CSS的笔记加理解总结归纳的,如有不对的地方,请留言指教, 学前了解: CSS中字母是不分大小写的; CSS文件可以使用在各种程序文件中(如:PH ...

随机推荐

  1. Cartographer源码阅读(2):Node和MapBuilder对象

    上文提到特别注意map_builder_bridge_.AddTrajectory(x,x),查看其中的代码.两点: 首先是map_builder_.AddTrajectoryBuilder(...) ...

  2. [py]python的time和datetime模块获取星期几

    import time import datetime #今天星期几 today=int(time.strftime("%w")) print today #某个日期星期几 any ...

  3. ANSI码和UNICODE码

    什么是ANSI,什么又是UNICODE呢? 其实这是两种不同的编码方式标准,ANSI中的字符采用8bit,而UNICODE中的字符采用16bit. (对于字符来说ANSI以单字节存放英文字符,以双字节 ...

  4. nodejs 网上下载图片到本地,并判断图片路径是否存在

    var http = require("http"); var fs = require("fs"); var server = http.createServ ...

  5. 《大道至简》第一章读后感Java伪代码

    在<大道至简>第一章中,周爱民先生引用一则<愚公移山>的寓言,引出了编程的根本:顺序.选择.循环.“愚公移山”的工程虽然庞大,但是可以通过极其简单的变成来完成.我身边的有一些人 ...

  6. Selenium基础知识(六)下拉列表定位

    1.下拉列表定位 要选择下拉列表中的元素,要先定位到,下拉列表元素,然后可以通过xpath去点击,表内内容 例如,百度搜索-->百度设置-->搜索设置-->选择下拉列表框内" ...

  7. Docker下操作指令

    Docker下操作指令 以mysql为例 1.搜索镜像: #docker search mysql 2.拉取镜像 #docker pull mysql:5.7 3.加载镜像并绑定端口: #docker ...

  8. java字符串转换总结

    1.byte[]转String String str = new String(strByte); 2.String转byte[] byte[] byteArr = str.getBytes(); 3 ...

  9. css 文字样式

    Gradient 3D text 代码区域 /*css */ body { background-color: #272727; } h1 { font-family: "Arial&quo ...

  10. HDU 1014 Uniform Generator(题解)

    Uniform Generator Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...