目标:正常阅读kotlin代码,能在此基础上进行简单修改
内容:与Java进行比较,学习kotlin基础代码规范
1.基础语法和代码格式
package com.runoob.main
import java.util.*
fun test() {}//普通函数
class Runoob {}//类定义
fun main(args:Array<String>){}//程序入口
由于没有分号; 记录代码段,代码格式类比python
1.1函数定义
用关键字fun定义函数
//Kotlin
fun sum(a: Int, b: Int): Int { // Int 参数,返回值 Int
return a + b
}
//Java
int sum(int a,int b){
return a+b;
}
表达式作为函数体,返回类型自动推断:
//kotlin
fun sum(a: Int, b: Int) = a + b
public fun sum(a: Int, b: Int): Int = a + b // public 方法则必须明确写出返回类型
//Java
Predicate<Integer> test1 = a -> a>100;
Predicate<Integer> test2 = a -> {
a=a+10;
return a>100;
};
无返回值的函数(类似Java中的void):
//kotlin
fun printSum(a: Int, b: Int): Unit {
print(a + b)
}
// 如果是返回 Unit类型,则可以省略(对于public方法也是这样):
public fun printSum(a: Int, b: Int) {
print(a + b)
}
//Java
void printSum(int a,int b){
print(a+b)
}
1.2可变长参数函数
1.传入参数长度可变化,但是得小心使用,避免越界
2.优先匹配固定参数
//kotlin
fun vars(vararg v:Int){
for(vt in v){
print(vt)
}
}
// 测试
fun main(args: Array<String>) {
vars(1,2,3,4,5) // 输出12345
}
//Java
void vars(String... args){}
void vars(String a,String[] args){} //优先匹配a
1.3lambda(匿名函数)
// kotlin
fun main(args: Array<String>) {
val sumLambda: (Int, Int) -> Int = {x,y -> x+y}
println(sumLambda(1,2)) // 输出 3
}
//Java
Comparator<Integer> comparator = new Comparator<Integer>(){
@Override
public int compare(Integer o1,Integer o2){
return o1>o2?:1:-1;
}
}
Comparator<Integer> comparator = (o1,o2)->o1>o2?:1:-1;//只存在一个重写函数时,可省略return
1.4定义常量与变量
可变变量定义:var 关键字
不可变变量定义:val 关键字,只能赋值一次的变量(类似Java中final修饰的变量)
//kotlin
var <标识符> : <类型> = <初始化值>
val <标识符> : <类型> = <初始化值>
//Java
var <标识符> = <初始化值>;
<数据类型> <标识符> = <初始值>;
final int a = 1;
//kotlin
/*
常量与变量都可以没有初始化值,但是在引用前必须初始化
编译器支持自动类型判断,即声明时可以不指定类型,由编译器判断。
*/
val a: Int = 1
val b = 1 // 系统自动推断变量类型为Int
val c: Int // 如果不在声明时初始化则必须提供变量类型
c = 1 // 明确赋值
var x = 5 // 系统自动推断变量类型为Int
x += 1 // 变量可修改
//Java
var a=1;
var b=0.1;
int a;
a=1;
//var a; 错误
1.5NULL检查机制
对于可为空的数据类型,要做判空处理
//kotlin
//类型后面加?表示可为空
var age: String? = "23"
//抛出空指针异常
val ages = age!!.toInt()
//不做处理返回 null
val ages1 = age?.toInt()
//age为空返回-1
val ages2 = age?.toInt() ?: -1 //相对java判空方便很多
1.6区间
for (i in 1..4) print(i) // 输出“1234”
for (i in 4..1) print(i) // 什么都不输出
if (i in 1..10) { // 等同于 1 <= i && i <= 10
println(i)
}
// 使用 step 指定步长
for (i in 1..4 step 2) print(i) // 输出“13”
for (i in 4 downTo 1 step 2) print(i) // 输出“42”
// 使用 until 函数排除结束元素
for (i in 1 until 10) { // i in [1, 10) 排除了 10
println(i)
}
2.基本数据类型
2.1基本数值类型
类型 | 位宽度 |
---|---|
Double | 64 |
Long | 64 |
Float | 32 |
Int | 32 |
Short | 16 |
Byte | 8 |
kotlin中没有基本数据类型,只有对象,定义一个变量,则会创建一个对象。
因此比较变量时,参考java中String比较。三个等号 === 表示比较对象地址,两个 == 表示值比较
2.2类型转换
较小类型不是较大类型的子类型,不能小到大隐式转换,只能显示转换。
隐式转换
//Kotlin
val b: Byte = 1 // OK, 字面值是静态检测的
val i: Int = b // 错误
//Java
//可隐式从小到大转换,Java有基本数据类型
byte a=1;
int b=a;
显式转换
//Kotlin
val b: Byte = 1 // OK, 字面值是静态检测的
val i: Int = b.toInt() // OK
//Java
byte a=1;
int b=Integer.valueOf(a);
//Java对每个基本数据类型有对应封装的对象,每个对象中有静态方法进行类型转换
System.out.println(b);// 1
每个数据类型都有以下方法进行数据转换,上述已知kotlin在创建变量时会创建对象,因此可以直接使用 变量名.方法名
toByte(): Byte
toShort(): Short
toInt(): Int
toLong(): Long
toFloat(): Float
toDouble(): Double
toChar(): Char
2.3位操作
对于Int和Long类型,还有一系列的位操作符可以使用,分别是:
shl(bits) – 左移位 (Java’s <<)
shr(bits) – 右移位 (Java’s >>)
ushr(bits) – 无符号右移位 (Java’s >>>)
and(bits) – 与
or(bits) – 或
xor(bits) – 异或
inv() – 反向
2.4字符
kotlin中的字符不能直接和数字操作
转义字符 | 作用 |
---|---|
\t | 制表符 |
\r | 光标回到开头 |
\n | 回车符 |
\b | 后退一格 |
\’ | ’ |
\‘’ | ‘’ |
\\ | \ |
\$ | $ |
2.5字符串
String不可变
1、通过[]访问某个字符,for循环可遍历
2、通过三个引号可以" " "扩起来得到多行字符串
3、通过$ <String> 和 $<{任意表达式}>进行字符串填充
for (c in str) {
println(c)
println(str[0])
}
fun main(args: Array<String>) {
val text = """
多行字符串
多行字符串
"""
println(text) // 输出有一些前置空格
}
fun main(args: Array<String>) {
val text = """
|多行字符串
|菜鸟教程
|多行字符串
|Runoob
""".trimMargin()
println(text) // 前置空格删除了
}
fun main(args: Array<String>) {
val s = "runoob"
val str = "$s.length is ${s.length}" // 求值结果为 "runoob.length is 6"
println(str)
}
3.条件语句
3.1if表达式
if类比Java
3.2when表达式
类比Java switch,但是进一步扩展了
//kotlin
//满足一个条件则跳出,else相当于switch的default
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")
}
//Java
switch(a){
case a==1:{break;}
case a==2:{break;}
default:{break;}
}
3.3while 和 do while
类比Java
4.类
4.1类构造
类构造器在类名头部,用constructor(),每个类默认有一个public的空主构造函数
如果主构造器没有任何注解,也没有任何可见度修饰符,那么constructor关键字可以省略。
主构造器中不能包含任何代码,可用init进行初始化
//Kotlin
class Person constructor(firstName: String) {
init {
println("FirstName is $firstName")
}
}
//Java
class Person{
Person(String firstName){
}
}
次构造器
class Person {
constructor(parent: Person) {
parent.children.add(this)
}
}
类属性声明的完整语法:
var <propertyName>[: <PropertyType>] [= <property_initializer>]
[<getter>]
[<setter>]
class Person {
var lastName: String = "zhang"
get() = field.toUpperCase() // 将变量赋值后转换为大写
set
var no: Int = 100
get() = field // 后端变量
set(value) {
if (value < 10) { // 如果传入的值小于 10 返回该值
field = value
} else {
field = -1 // 如果传入的值大于等于 10 返回 -1
}
}
var heiht: Float = 145.4f
private set
}
// 测试
fun main(args: Array<String>) {
var person: Person = Person()
person.lastName = "wang"
println("lastName:${person.lastName}")
person.no = 9
println("no:${person.no}")
person.no = 20
println("no:${person.no}")
}
4.2抽象类
关键字 open 表示与java final完全相反的作用
abstract定义的关键类默认有open作用,不用再加
4.3类修饰符
修饰符 | 作用 |
---|---|
public | 类在所有地方可用 |
private | 仅在当前类可用 |
protected | 仅在当前类及其子类中可用 |
internal | 仅在当前模块可用 |
5.面向对象
kotlin所有类继承Any类
Any中包含三个函数
equals()
hashCode()
toString()
open class Base(p: Int) // 定义基类,要被继承的类需用open修饰
class Derived(p: Int) : Base(p)
接口
运行方法有默认实现,与抽象类的区别在于:
- interface属性只能是var,且不能设初始值
- 一个类可以实现多个接口
- 实现接口时,属性必须被重写
//重写方法
interface MyInterface {
fun bar() // 未实现
fun foo() { //已实现
// 可选的方法体
println("foo")
}
}
class Child : MyInterface {
override fun bar() {
// 方法体
}
}
//重写属性
interface MyInterface{
var name:String //name 属性, 抽象的
}
class MyImpl:MyInterface{
override var name: String = "runoob" //重写属性
}