一,简介
- Kotlin是JetBrains开发的基于JVM的语言,Kotlin可以编译成Java字节码,也可以编译成JavaScript,方便在没有JVM的设备上运行。
- 特点:比Java更安全,能够静态检测常见的陷阱。如:引用空指针。代码更易表现,书写方便,便于阅读。支持函数式编程,如:使用lambda表达式来更方便地解决问题。
- Kotlin是一种现代化的语言,语法汇集了很多语言的优点,是未来编程的一种趋势。
二,开发环境
- 开发软件:IntelliJ IDEA和AndroidStudio
- IntelliJ IDEA下载地址:http://www.jetbrains.com/idea/download/#section=windows
- AndroidStudio下载地址:https://developer.android.google.cn/studio/index.html
- 如果是老版本需要手动安装Kotlin插件
三,数据类型
(1),开始编写第一段代码,这里使用IntelliJ IDEA来讲解,创建一个Kotlin文件,Kotlin是以kt为后缀
然后写一个mian方法打印一句话
(2),基本数据类型
①,数据类型和Java一样也有integer,float,boolean,不同的是Kotlin都是以对象的形式出现的。
val i: Int = 1
val f: Float = 1f
val d: Double = 1.0
val l: Long = 1
val sh: Short = 1
val b: Boolean = true
val s: String = "Hello Word"
val i = 1
val f = 1f
val d = 1.0
val l = 1
val sh = 1
val b = true
val s = "Hello Word"
val代表常量,命名规则 :变量名+冒号+数据类型。上边代码效果是一样的,这里数据类型可以不写,编译器会自动识别。代码后边的分号也不是必须的。
②,在Java中可以隐式转换,一个int类型是可以直接赋值给double类型的。而Kotlin不能隐式转换,需要强转。
//Kotlin代码
val i: Int = 8
val d: Double = i.toDouble()
//Java代码
int i=8;
double d=i;
③,String可以像数组一样被访问,也可以迭代。
val s = "Hello Word"
val c = s[2]
for(c in s){
println(c)
}
④,这里‘’‘’和Java中的‘’equals‘’是等价的。‘’=‘’和Java中的‘’==‘’是等价的
val s: String = "Hello Word"
val s1: String = String(charArrayOf('H', 'e', 'l', 'l','o', ' ', 'W', 'o', 'r', 'd'))
println(s == s1) //打印结果 true
println(s === s1)//打印结果 false
⑤,在Kotlin中引入了字符串模板,用“$”表示
val num1 = 3
val num2 = 4
println("" + num1 + "+" + num2 + "=" + (num1 + num2))//java方式
println("$num1+$num2=${num1 + num2}")//Kotlin方式
⑥,空类型安全
在Java中定义一个变量,调用变量时通常会进行空值判断,否则会有空指针的异常。而在Kotlin程序会对空类型进行检测,则不会出现空指针异常。如果想让变量为空,需要在变量后边加上?
var name: String = null //这里编译器是不会通过的,不能是null
var sex: String? = null // 这样是没问题的
println(sex.length) //这样是不行的,编译不通过
println(sex?.length) //这样没问题
println(sex!!.length) // 注意操作符!!,只有在sex不为空的情况下才能使用,否则会抛异常
在集合中可以使用filterNotNull过滤掉null类型的数据
val list : List<String?> = listOf(
"red",
"orange",
"yellow",
"gree",
"blue",
null
)
//过滤掉null
val colors:List<String> = list.filterNotNull()
⑦,在Java中有基本类型和装箱类型,如:int基本类型,Integer装箱类型。Kotlin中不用关心这些,编译器会自动选择。
(3),变量
- 在Kotlin中, 一切都是对象。所以,所有变量也都是对象(也就是说,任何变量都是根据引用类型来使用的)
- Kotlin的变量分为 var (可变的) 和 val (不可变的)。
- 尽量在Kotlin中首选使用val不变值,这样做的好处是可预测的行为和线程安全。
(4),包(package)
在Kotlin中也沿袭了Java的 package 这个概念,同时做了一些扩展。我们可以在一个包中引用另一个包
在student包中引用了teacher包,这里是可以编译通过的,调用Mark类的时候引用的也是teacher。可以看出Kotlin中我们可以修改包的引用,但是为了项目结构更加清晰一般我们不会这么做。
如果一个类类名比较长,调用时还可以起个别名。这里调用Mark类时,给Mark类起名为a,直接用a调用此类。
(5),区间
区间就是数学中的概念,开区间和闭区间。比如声明一个0到100的区间,区间也可以迭代。
val intR:IntRange=0..100 //闭区间 [0,100]
val intR1:IntRange=0 until 100 // 前闭后开 [0,100)=[1,99]
//循环输出区间中的值
for(i in intR){
println(i)
}
(6),数组
数组和Java中的一样,我们看下如何定义数组。
创建数组有如下两种方式:
- 使用arrayOf(),arrayOfNulls(),emptyArray()函数。
- 使用Array(size:Int,init:(Int) -> T)构造器
//创建包含元素的数组(相当于Java数组的静态初始化)
val array:IntArray= intArrayOf(1,2,3,4,5)
val charArray:CharArray = charArrayOf('H','e','l','l','0')
val stringArray:Array<String> = arrayOf("你是","我的","眼")
//创建指定长度,元素为null的数组(相当于Java数组的动态初始化)
var douArray = arrayOfNulls<Double>(5)
var intArray = arrayOfNulls<Int>(5)
//创建长度为0的空数组
var strArray= emptyArray<String>()
//创建指定长度,使用Lambda表达式初始化数组元素
var array = Array(5, { (it * 2 + 97).toChar() })
println(array.size) // 数组的长度
stringArray[1]="他" //修改数组的值
println(array.slice(2..3)) //数组的截取
//数组遍历
for(i in array){
println(i)
}
四,类和函数
(1),如何定义一个类,类的属性
①,类
class Student(name: String, sex: String, age: String)
定义类用class关键字,如果类中没有其他内容,可以省去大括号,并且这个类有一个默认的构造器
class Student(name: String, sex: String, age: String){
init {
//默认构造器函数
println("学生:$name 性别 $sex 年龄 $age")
}
}
//调用这个类
val s:Student= Student("张三","男","20")
init就是这个类默认的构造函数,类的调用不再需要new关键字。
②,属性
Java代码中定义一个属性,需要写它的set和get方法。Kotlin中默认有set和get方法
//Java代码
public class Student {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
...
Student student=new Student();
student.setName("小明");
String name=student.getName();
//Kotlin代码
class Student {
var name: String = ""
}
...
val student=Student()
student.name="小明"
val name=student.name
我们也可以修改默认的方法,如果我们需要在set和get中访问自身的值,可以通过field这个预留字段来访问。
class Student {
var name: String = ""
get() = field.toUpperCase()
set(value) {
field="name=$name"
}
}
(2),类的继承
class Student(name: String, sex: String, age: String):Course(name)
open class Course(name:String)
- 学生类继承课程类,继承这里用 “:” 表示。我们可以发现用冒号的地方真多,变量的声明,类的继承,函数的返回值类型,都用到了 “:”进行表示。
- 默认任何类都是继承Any,这里和Java中的(Object)类似。
- 所有类默认是不可继承的,如果想继承需要用open或abstract关键字。
- 当我们只有一个构造器时,需要从父类继承下来的构造器中指定需要的参数,这里用作替换Java中的super
(3),函数
①,这是一个main函数,函数可以用fun关键字来定义。
fun main(args: Array<String>) {
println("Hello word")
}
这个函数没有返回值,如果没有指定函数的返回值,它返回就是Unit,和Java中的void类似。但是Unit也是一个对象。
②,我们也可以指定函数的返回值,这几种写法是一样的。如果返回的只是一个结果,那么可以省略大括号,直接等于返回值。也可以直接省略返回值类型。
//写法1
fun add(a: Int, b: Int): Int {
return a + b
}
//写法2
fun add (a:Int,b:Int):Int=a+b
//写法3
fun add(a: Int, b: Int) {
return a + b
}
//写法4
fun add (a:Int,b:Int)=a+b
④,我们也可以给函数的参数指定默认值,指定默认值的参数可以不传。注意:如果第一个参数有默认值,其他参数没有默认值,那么依然需要传入参数。与Java中方法的重载很类似的,Kotlin相当于把多个重载方法合并成了一个。
//Kotlin代码
fun student(name: String, sex: String = "男") {
println("名字:$name 性别:$sex")
}
student("张三")
student("小红", "女")
//Java代码
void student(String name, String sex) {
System.out.println("name=" + name + ",sex=" + sex);
}
void student(String name) {
System.out.println("name=" + name);
}
(4),构造函数
构造函数分为两种:主构造函数和次构造函数
每个类默认都有不带参数的主构造函数,主构造函数没有函数体。如下在Student的主构造函数传入两个参数,由于主构造函数没有函数体,想在主构造函数中写逻辑可以在init中进行。次构造函数用constructor修饰
class Student(val no:String,val grade:Int) {
init {
}
}
(5),修饰符
Java中:public,private,protected,default
Kotlin中:public,private,protected,internal
其中private是一样的,public也是一样的,只不过在kotlin中是默认的。protected在Java中表示对当前类,子类和同一包路径下可见,在kotlin中只对当前类和子类可见。在kotlin中只对同一模块可见使用internal修饰。
(6),扩展函数
扩展函数就是可以在系统类的基础上扩展新的函数,比如:实现字符串相乘,扩展函数用operator关键字修饰。
operator fun String.times(n: Int): String {
val builder = StringBuilder()
repeat(n) {
builder.append(this)
}
return builder.toString()
}
使用
val str = "hello" * 3
五,表达式
(1),Lamdba表达式
①,Lambda表达式是一个匿名函数,将行为像数据一样传递,表达式使用"->“将参数和主体分开,”->"前面是参数部分,后面这是主体部分。Lambda表达式在Java8中引入的,具体用法这里不再讲解,读者可以阅读有关文章。这是一段Java代码,使用了Lambda表达式new一个线程。
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("lambda");
}
}).start();
new Thread( () -> System.out.println("lambda") ).start();
//这段代码可以看出,把一个内部类当成一个参数传入,代码简化了很多
②,再看下Kotlin代码如何使用Lambda表达式。
//匿名函数
val add=fun (a: Int, b: Int): Int {
return a + b
}
//Lambda表达式写法
val add={a:Int,b:Int->a+b}
//Lambda表达式,没有"->"
val student={
println("我是学生")
}
Lambda表达式和匿名函数类似。可以看到"->“前边是参数,”->“后边是返回值。当然”->"也不是必须的。就像这个学生函数,不需要参数,不需要返回值。
③,调用Lambda表达式,传入两个值,输出2。这里我们注意到,在调用Lambda时用到了小括号。
println(add(1,1))
(2),分支表达式
在kotlin中if和else 可以是表达式,也可以是代码块
//常规写法
fun max1(a: Int, b: Int): Int {
var num: Int
if (a > b) {
num = a
} else {
num = b
}
return num
}
//代码块写法,表达式可以是代码块
fun max(a: Int, b: Int): Int {
val num = if (a > b) {
a
} else {
b
}
return num
}
注:kotlin中没有三元表达式true? 1: 0 ,对应的写法 if(true) 1 else 0
(3),when表达式
when表达式和switch类似,在kotlin中没有switch,替代它的是when表达式。else就相当于switch中的default
val x = -1
when (x) {
is Int -> print("is Int")
-1, 0 -> print("x == 0") // 同时满足-1和0的条件,相当于switch中去掉break
1 -> print("x == 1")
2 -> print("x == 2")
else -> {
print("") // 不是上述条件 相当于switch中的default
}
}
(4),while表达式
while循环和do while循环和Java一样
var count = 0
//当count小于8时,执行循环体
while (count < 8) {
print("count:${count}")
count++
}
(5),for-in表达式
for-in循环,用于数组,集合,字典的遍历,for-in循环无需声明常量。break可以终止循环和Java一样,另外break也可以终止外层循环,这就需要break后边要跟一个标签。如示例2其中jump@就是标签,在外层循环体外声明jump@标签,break被指定终止循环的标签,这样就可以终止外层循环。
//示例1
for (i in 0 until 10){
print("i=${i}")
if(i==4){
break
}
}
//示例2
jump@ for (i in 0 until 10) {
//内层循环
for (j in 0 until 5) {
if (j == 3) {
break@jump
}
}
}
continue和Java一样,可以忽略循环中剩下的语句,如示例1。另外和break类似,continue也可以声明标签,如示例2,j的值永远超不过4,当j等于4时continue@jump结束了外层循环的当次循环。
//示例1
for(i in 0 until 10){
print("打印 i=${i}")
if(i==4){
//忽略剩下的语句
continue
}
print("continue i=${i}")
}
//示例2
jump@ for(i in 0 until 10){
for(j in 0 until 10) {
print("打印 i=${i} j=${j}")
if (j == 4) {
//忽略剩下的语句
continue@jump
}
}
}
下一篇:kotlin进阶