乐趣区

关于android:Kotlin实战二Kotlin基本要素

前言

本章咱们将学习怎么用 kotlin 申明任何程序都存在的基本要素:变量、函数、类以及属性的概念

一、函数和变量

1.1 Hello World

让咱们以一个经典的例子开始:打印“Hello, world!”

fun main(args: Array<String>) {println("Hello, world!") 
}

从下面代码咱们能看到哪些特点呢?

  • 关键字 fun 用来申明一个函数。(没错,kotlin 就是这么 fun)
  • 参数类写在参数名字的前面,变量的申明也是如此。
  • 函数能够在文件的最上层中申明,你没必要把它放到一个类中。
  • 数组就是类。不像 Java,Kotlin 没有特定的申明数组的语法。
  • 用 println,而不是 System.out.println。Kotlin 规范库提供了很多规范 Java 库函数的包装,这有更简洁的语法。println 就是其中之一。
  • 和很多古代语言一样,能够省略每行代码结尾的分号。

1.2 函数

1.2.1 函数类型

下面曾经看了一个没有返回值得函数,上面咱们看一个有返回值的函数:

fun max(a: Int, b: Int): Int {return if (a > b) a else b 
}
println(max(1, 2)) //2

咱们看到返回类型放在了参数列表之后。

留神:在 Kotlin 中 if 是个有返回值的表达式。相似于 Java 中的三目运算符(a > b)? a : b

函数申明以 fun 开始,函数名紧随其后,例子中函数名是max,接下来是参数列表,之后跟着返回类型,之间用冒号隔开。

无返回类型

fun 函数名(参数列表){函数体}

有返回类型

fun 函数名(参数列表):返回类型{函数体}

语句 表达式 在 Kotlin 中,if 是个表达式,而不是一个语句。语句和表达式的区别在于,表达式是一个值,能够被用作另外表达式的一部分;而语句总是一个蕴含它的代码块内的顶层元素,没有本人的值。在 Java 中,所有的控制结构都是语句,然而在 Kotlin 中,大部分控制结构,除了循环(for , do 和 do/while),是表达式。联结控制结构和其余的表达式,能够让你简洁表白许多通常的模式。另外一方面,在 Java 中赋值是表达式,然而在 Kotlin 中变成了语句。这无效防止了比拟和赋值之间的混同,这个混同也是谬误的一个起源。

1.2.2 表达式函数体

能够让后面的函数变得更简略。因为他的函数体是由单个表达式形成,能够用这个表达式作为残缺的函数体,并去掉花括号和 return 语句:

fun max(a: Int, b: Int): Int = if (a > b) a else b

如果用花括号来表白函数主体,咱们叫这个函数为 代码块体 ,如果间接返回表达式,咱们叫它为 表达式体INTELLIJ IDEA 提醒 : IntelliJ IDEA 提供了在两种不同函数格调“Convert to expression body”和“Convert to block body”之间的转换

表达式体的函数在 Kotlin 代码中很常见,不光用在一些简略的函数中,也用在许多简单的表达式中,如:if、when、try 等,后续介绍

1.2.3 类型推导

咱们的 max 函数还能够进一步简化,如下:

fun max(a: Int, b: Int) = if (a > b) a else b

为什么函数没有返回类型的申明呢?作为一个动态类型语言,Kotlin 不是要求每个表达式都应该在编译期具备类型吗?事实上,每个变量和表达式都有返回类型。然而对于表达式体的函数,编译器能够剖析作为函数体的表达式,用它的类型作为返回类型,即便没有显示的写进去。剖析的这个类型通常叫 类型推导(type inference)

留神:省略返回类型仅仅在表达式体的函数中容许。有代码块体的有返回值的函数,你必须指明返回类型和显示的返回语句。理论中的函数通常十分长,可能蕴含很多返回语句,有显示的返回类型和语句能够帮忙你疾速的晓得什么被返回。

1.3 变量

在 Java 中,你用类型申明变量。然而在 Kotlin 中,许多变量的类型都能够省略,所以在 Kotlin 中以关键字开始,而后是变量名,最初加上类型(也能够不加)。省略类型:

val question = "The Ultimate Question of Life, the Universe, and Everything"
val answer = 42

显示类型:

val answer: Int = 42

不可省略类型: 变量没有初始化器,须要显示的指出

val answer:Int
answer = 42

可变变量和不可变量

  • val(来源于 value)— 不变的援用。一旦申明为 val 的量初始化后,不可能从新赋值。对应于 Java 外面的 final 变量
  • var(来源于 variable)— 可变的援用。变量的值能够扭转。对应于 Java 外面的失常的变量(非 final)

通常,尽量申明所有的变量为 val 关键词。只有有须要的时候,才变为 var。应用不可变援用、不可变对象及无无副作用的函数让你的代码更靠近函数式编程格调

定义了 val 变量的代码块执行期间,val 变量只能进行惟一一次初始化。然而,如果编译器能确保只有惟一一条初始化语句被执行,能够依据条件应用不同的值来初始化它:

val message: String
if (canPerformOperation()) {
    message = "Success"
    // ... perform the operation } 
else {message = "Failed"}

留神:只管 val 援用本身是不可变得,然而它指向的的对象可能是可变的:

val languages = arrayListOf("Java") // 申明不可变的援用
languages.add("Kotlin")// 扭转援用指向的实例

留神:只管 var 关键词容许变量扭转他的值,然而它的类型是确定的:

var answer = 42 
answer = "no answer"// 编译谬误:类型不匹配

编译器只会依据初始化器来推断变量的类型,在决定类型的时候不会思考后续的赋值操作。

如果你想在变量外面存储一个不匹配的类型的值,你必须转换或者协变这个值到正确的类型。

1.4 更容易的字符串格式化:字符串模板

fun main(args: Array<String>) { 
    // 打印“Hello,Kotlin”,如果输出参数为 Bob,则打印“Hello,Bob”val name = if (args.size > 0) args[0] else "Kotlin" 
    println("Hello, $name!") 
}

这个例子引进了一个性能叫字符串模板(string templates)。和其余脚本语言一样,Kotlin 容许在字符串字面量中,通过 $ 字符放在变量名后面,援用本地变量。这个同 Java 中的字符串连贯(“Hello, ” + name + “!”), 然而更加紧凑和有效率(注:都是创立 StringBuilder,增加常量局部和变量值,Java 虚拟机有优化)。

如果你援用一个不存在的本地变量,因为表达式会动态查看,这些代码会编译不胜利。如果你想在字符串中蕴含
x,而不是把 x 翻译为一个变量的援用。

不限于一个简略的变量名,你也能够用更加简单的表达式,仅仅只有在表达式括上花括号:

fun main(args: Array<String>) {// 用 ${}插入 args 数组的第一个元素
    if (args.size > 0) {println("Hello, ${args[0]}!") } 
}

你也能够双引号内陷双引号,只有他们是在同一个表达式:

fun main(args: Array<String>) {println("Hello, ${if (args.size > 0) args[0] else"someone"}!")
}

二、类和属性

面向对象编程可能不是什么陈腐话题,Kotlin 这方面也似曾相识,然而你会发现许多常见的工作应用更少的代码就能够实现。

让咱们看看一个简略的 JavaBean 的 Person 类,当初只蕴含一个 name 属性:

/* Java */ 
public class Person { 
    private final String name;

    public Person(String name) {this.name = name;}

    public String getName() {return name;}
}

在 Java 中,构造方法的办法体经常蕴含反复内容,把参数赋值给有着雷同名称的字段。在 Kotlin 中,这个逻辑不须要如此多的样板代码。

/* Kotlin*/ 
class Person(val name: String)

这品种(只有数据没有其余代码)通常被叫做 值对象

留神:从 java 到 Kotlin 的转换过程中 public 修饰符隐没了。在 Kotlin 中 public 是默认的可见性。

2.1 属性

  • 在 java 中,如果你想让类的使用者拜访到数据,须要提供拜访办法:一个 getter、可能有一个 setter,setter 可能蕴含一些额定的逻辑,验证传递值,或者发送值变动的告诉等等。
  • 然而在 Koltin 中,属性是头等的语言特信,齐全代替字段和访器办法。应用 val 和 var 关键字。申明 val 的属性只读,var 是可变的
class Person( 
    val name: String, // 只读属性: 主动生成一个域和简略的 getter
    var isMarried: Boolean // 可写属性:一个域,getter 和 setter
)

接下来咱们看下如何应用下面定义好的 Person 类:

val person = Person("Bob", true)
println(person.name)// Bob
println(person.isMarried) //true

当初能够间接援用属性,不再须要 getter,逻辑没变,代码更加简洁。

小贴士:

  • 你能够在 Java 定义的类中应用 Kotlin 的属性语法。在 Java 类中的 getter 能够在 Kotlin 中 val 属性获取,getter/setter 能够通过 var 属性获取。比方,如果在 Java 类定义了 setName 和 setName 的办法,那么能够通过叫 name 的属性获取。如果类定义了 isMarried 和 setMarried 办法,相应的 Kotlin 属性叫 isMarried。

2.2 自定义属性拜访器

这个局部,你将看到怎么自定义实现一个属性拜访器。假如你申明了一个长方形,它能够通知是不是一个正方形。你没必要用独自的域存储这个信息,因为你须要动静查看高是否等于宽:

class Rectangle(val height: Int, val width: Int) { 
    val isSquare: Boolean 
    get() { //Property getter declaration
        return height == width
    } 
}

isSquere 属性不须要一个域来存储它的值。它仅仅是自定义实现的 getter。

val rectangle = Rectangle(41, 43)
println(rectangle.isSquare) //false

2.3 Kotlin 源码布局:目录和包

Java 把所有的类放进包外面。Kotlin 也像 Java,有包的概念。每个 Kotlin 文件在结尾有 package 语句,文件中所有的申明 (类、函数和属性) 将放在这个包下。如果其余的文件在同一包下,外面所有的定义能够间接应用;如果这些定义在不同包外面,那么他们须要导入。就像在 Java 中,导入语句搁置在文件的结尾,应用 import 关键词。上面是个例子,展现包申明和导入语句:

package geometry.shapes // 包申明

import java.util.Random // 导入规范 Java 库类

class Rectangle(val height: Int, val width: Int) {
    val isSquare: Boolean
        get() = height == width} 

fun createRandomRectangle(): Rectangle {val random = Random()
    return Rectangle(random.nextInt(), random.nextInt()) 
}

接下来看一下 java 和 kotlin 的目录构造

如上图:java 中,目录层级构造照搬了包层级构造

如上图:kotlin 中,不须要遵循目录层级构造

在 kotlin 中,能够把多个类放在同一个文件中,文件的名字还能够随便抉择。

然而,在大多数状况下,追随 Java 目录构造和依据包构造把源码组织成目录,是最佳实际。特地是 Kotlin 和 Java 混合的我的项目,保持这样的构造特地重要。因为这样做能够让你逐渐迁徙代码,而没有引入意外的状况。然而当类很小的时候(在 Kotlin 中,这些常常存在)。请你不要犹豫把多个类合成到同一个文件。

总结

  • fun 关键字用来申明函数。val 关键字和 var 关键字别离用来申明只读变量和可变变量
  • 字符串模板帮忙你防止繁琐的字符串拼接。在字符串前加上 {} 突围一个表达式,来把值注入到字符串中。
  • 实体类(值对象类)在 Kotlin 中以更简略的形式示意。
  • 在 kotlin 中,能够把多个类放在同一个文件中,文件的名字还能够随便抉择。

文章转自 https://juejin.cn/post/684490… 如有侵权,请分割删除。

相干视频举荐:

Android 性能优化学习【二】:APP 启动速度优化_哔哩哔哩_bilibili
【Android 进阶零碎学习】:字节码插桩技术实现自动化办法耗时记录_哔哩哔哩_bilibili
Android 性能优化学习【二】:APP 启动速度优化_哔哩哔哩_bilibili
【Android 面试专题】:面试又被问到过程间通信,你却连 Binder 是什么都不晓得?_哔哩哔哩_bilibili
BAT 面试技巧——Android 面试必问的网络编程你理解多少?_哔哩哔哩_bilibili

退出移动版