kotlin教程(1)
最近在读《kotlin 实战》,这里做一下笔记,就当复习总结了,开头先附上官网文档的地址 https://www.kotlincn.net/
该篇文档主要讲述kotlin的基本要素,变量、函数、类,和Java之间的异同点。
函数和变量
Hello World 开始
public class First{
public static void main(String[] args) {
System.out.println("Hello World");
}
}
而kotlin中的代码就简单很多了
// kotlin默认的返回值就是Unit,即对应Java中void方法,所以下面两行的写法是等价的
// fun main(args: Array<String>): Unit {
fun main(args: Array<String>) {
printlin("Hello World)
}
从这两段代码中,我们可以知道
- 用关键字fun生命一个函数
- 参数的类型生命实在名称后面,同理,变量的声明也是如此,eg. val a:Int = 10 (声明一个Int类型的变量,值为10)
- 函数可以定义在最外层,不需要放置在类中
- 数组就是类,kotlin没有声明数组类型的特殊语法,即 args:Array
等价 Java中的 String[] args - 使用println()是kotlin标准库(提供了许多比Java语法更简洁的包装)中的一个函数,代替了 System.out.println();
- 行尾可以省略分号
函数
上面的函数没有返回任何值,如果需要返回一个有意义的结果,需要在方法后声明返回类型,如下
fun max(a: Int, b: Int): Int {
return if (a > b) a else b
}
kotlin中没有三目运算符,可以使用上面的if else 语句来代替。kotlin中的if和Java中的if有点不一样,在kotlin中,if是表达式,而不是语句
** 语句和表达式的区别在于,表达式有值,并且能作为另一个表达式的的一部分使用,而语句则没有自己的值
上面的函数可以写的更加简单,因为函数体只有单个表达式。所以可以写成
fun max(a: Int, b: Int) = if (a > b) a else b // 这边因为可以从函数体中推断出返回的值为Int,所以也可以省去返回类型
```kotlin
在kotlin中有很多可以通过类型推导而省去显示写出来的操作,后面我们还会遇到。
## 变量
kotlin中声明变量以val和var关键字开始,然后是变量名称,最后可以加上类型(不加也可以)
```kotlin
val str = "hello"
// 下面两行是等价的
var a:Int = 10
var a = 10
// 如果变量没有被初始化,则必须指定类型,如下所示
val b:Int
b = 22
val -> 不可变引用,对应java的final变量
var -> 可变引用,对应java中的普通变量
需要注意的是,是虽然var关键字运营变量改变自己的值,但是类型无法改变,和java一样,是强类型的。
var num = 10
num = "ffff" // 错误,无法通过编译,类型不匹配
类和属性
kotlin中的类
/*java*/
public class Person{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
在kotlin实现上述的代码只需要一行
class Person(var name:String)
或者可以写成下面这种类似java的写法
class Person{
//默认实现了 getter 和 setter 方法
var name:String = "我必须初始化" // 类中声明的属性必须得初始化,否则编译报错
}
我们可以使用idea自带的kotlin反编译,来看看他生成的字节码反编译后的样子
public final class Person {
@NotNull
private String name;
@NotNull
public final String getName() {
return this.name;
}
public final void setName(@NotNull String var1) {
Intrinsics.checkParameterIsNotNull(var1, "<set-?>");
this.name = var1;
}
public Person(@NotNull String name) {
Intrinsics.checkParameterIsNotNull(name, "name");
super();
this.name = name;
}
}
这下看起来熟悉了吧
- kotlin中默认的可见性修饰符是public,而且默认的class是不能被继承的,如果可以被继承,必须加上open关键字 ,eg. open class Person{}
- kollin中可以使用data class XX{} 来生成一个pojo,和没有data相比,会多出toString和hashCode等方法
内部类
koltin 中默认是嵌套类( 对应 Java中的静态内部类)
区分内部类与嵌套类,很简单,内部类存储了外部类的引用,嵌套类却没有
class Outer {
val name = "MyNameIsOuter"
// inner说明是个内部类
inner class Inner {
fun printParent() {
// 访问外部类成员时指明类作用域
println(this@Outer.name)
}
}
}
fun main(args: Array<String>) {
Outer().Inner().printParent() // 输出: MyNameIsOuter
}
属性
声明一个属性的完整语法是
var
[
[
其初始器(initializer)、getter 和 setter 都是可选的 。属性类型如果可以从初始器 (或者从其 getter 返回值,如下文所示)中推断出来,也可以省略。
kotlin中定义了属性,val的会生成getter方法,var的会生成 setter和getter方法,
当然我们也可以自己定义
class Square(var height: Int, var width: Int) {
val isEqual: Boolean
get() {
return height == width
}
}
像上面这种定义是不会生成一个isEqual的属性的,具体的可以了解一下kotlin的幕后属性
匿名内部类和接口
koltin使用对象表达式创建匿名内部类实例:
简单来说,下面这段代码中的object是创建内部类的语法,然后fun前面的override说明该方法是被覆写的。
window.addMouseListener(object: MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
// ……
}
override fun mouseEntered(e: MouseEvent) {
// ……
}
})
如果是函数式接口(只有单个抽象方法的Java接口,即java8中带有的 @FunctionalInterface注解的接口),可以如下使用lambda的表达式创建
// 里面的 println("clicked") 就是函数式接口的具体实现,是不是非常简洁
val listener = ActionListener { println("clicked") }