Kotlin学习 基础类型
随着Kotlin被谷歌指定为Android的官方开发语言,Kotlin的使用者也越来越多,它不仅能编写服务端,也能编写移动端,也能编译成javacript,代码会被编译为字节码文件,运行在JVM上,Kotlin是基于JVM的静态语言,它是强类型的语言。
作为一个求上进的程序员,怎能放过学习现代的编程语言的机会呢。
用mac的同学可以直接使用命令安装:
$ brew update $ brew install kotlin
输入kotlin下载地址后找到下图:
点downloads出现下图:
下面就是配置环境变量了,配置和java类似,这里不再介绍了。
关于Kotlin基础类型的学习代码部分:
注释非常详细:
package com.william.testkt /** * Kotlin基础数据类型 */ fun main(args: Array<String>) { // 类型扩展 var aaa: Int? = null val bbb: Int = 22 println(aaa)//null // 编译为基础类型int val in1: Int = 200 val in2: Int = 200 println(in1 === in2)// true // 编译为Integer类型 val intg1: Int? = 200 val intg2: Int? = 200 println(intg1 === intg2)// false,若在byte取值范围内为true // 二进制 val bval1 = 0b101010 val bval2 = 0B1010110 // 十进制 val tenVal1 = 0x132 val tenVal2 = 0X1d // 字符串模板 println("bval1的值为:${bval1}")// bval1的值为:42 println("bval2的值为:${bval2}")// bval2的值为:86 println("tenVal1的值为:${tenVal1}")// tenVal1的值为:306 println("tenVal2的值为:${tenVal2}")// tenVal2的值为:29 // 分隔符增加可读性 val spilt1 = 1_000_000_000 val spilt2 = 123_234_234 val spilt3 = 1234_1234 println("${spilt1},${spilt2},${spilt3}")// 1000000000,123234234,12341234 // 编译报错,因为默认值的类型为Double // var f2: Float = 24.22 val d2 = 3.22e2 println("d2的值为:${d2}")// 322.0 val a = 0.0 // 正无穷大 println("2.0/a的值为:${2.0 / a},${-2.0 / a}")// Infinity,-Infinity // 所有正无穷大数值都相等 println(2.0 / a == 20000.0 / 0.0)// true // 0.0/0.0结果为非数 val nan: Double = a / a println("a/a的值为:${nan}")// NaN // 非数与自己都不想等 println(nan == nan)// false // 字符型 // 直接指定单个字符作为字符值 val aChar: Char = 'a' // 使用转义字符作为字符值 val covChar: Char = '\r' // 使用Unicode编码值来指定字符值 val ch: Char = '\u5475' // 将输出一个呵字符 println(ch) // 呵 // 定义一个'呵'字字符值 val hh: Char = '呵' // 将Char型变量当成Int型处理会报错 // var hhVal: Int = hh // 所有数值类型必须显示转换,不能隐式转换 var b_val: Byte = 70 var s_val: Short = 110 // 隐式转换报错,小转大 // var b : Short = b_val // 必须显示转换 var b: Short = b_val.toShort() var c: Byte = s_val.toByte() println("b:${b}, c:${c}")// b:70, c:110 val bb = 230 val cc: Byte = bb.toByte() println(cc)// -26 // 虽然缺乏隐式转换,但是在表达式中会基于上下文推断自动切换 var b_s = b_val + s_val println("b_s的值为:${b_s}")// b_s的值为:180 // b_s的值映射为java int println("b_s的类型为:${b_s.javaClass}")// b_s的类型为:int // 下面表达式中的b_val强转为Long val l_bs = b_val.toLong() + s_val.toByte() println("l_bs的值为:${l_bs},类型为:${l_bs.javaClass}")// l_bs的值为:180,类型为:long // toChar() var result = "" // 循环3次 for (i in 0..2) { // 生成一个26-122之间的Int类型的整数 val intVal = (Math.random() * 26 + 97).toInt() // 强转intVal为Char型 拼接result result = result + intVal.toChar() // result += intVal.toChar() } println(result)// 随机结果 // Char型值加减一个整数得到Char型值 var c1 = 'h' var c2 = 'j' println(c1 + 4)// 输出l println(c1 - 4)// 输出d // 2个Char型值相减得到整型值,不能相加 println(c1 - c2)// 输出-2 // 浮点型之间的显示转换 var f_: Float = 2.3f var d_: Double = 4.5 // 强转为Double才能赋值给d var d: Double = f_.toDouble() println("d的值为: ${d}")// 2.299999952316284 // 强转Float, 表达式推断类型 var f_1 = f_ * d_.toFloat() // 推算结果为等级最高的类型 // Double var d_2 = f_ * d_ var other: Int = 5 // Double var totald_ = d_ * other // Int var totald_2 = d_.toInt() * other // f_1的类型为:float,d_2的类型为:double,totald_的类型为: double,totald_2的类型为: int println("f_1的类型为:${f_1.javaClass}," + "d_2的类型为:${d_2.javaClass}," + "totald_的类型为: ${totald_.javaClass}," + "totald_2的类型为: ${totald_2.javaClass}") // 表达式类型自动提升 var s_val2: Short = 20 // 右边为Int行,左边为Short型,编译错误 // s_val2 = s_val2 - 2 // 正确的表达式类型提升 var f: Byte = 40 var g: Short = 90 var i: Int = 20 var m: Double = .3 // 右边表达式最高等级的操作数为m,即右边结果为Double类型,dddd结果即为Double型 var dddd = f + g + i * m println(dddd)// 136.0 // 同java ,int相除除不尽取整 println(8 / 3)// 2 // + 加号连接符和运算符 println("android__" + 'a' + 88)// android__a88 println('a' + 2 + "__android")// c__android // Boolean 型 var boo1: Boolean = true var boo2: Boolean = false println("boo1:${boo1}, boo2:${boo2}")// boo1:true, boo2:false // null安全,可空和非空 var string = "kotlin" // 因为可能会转换失败返回null,所以不能赋值给Int型,编译错误 // var number1: Int = string.toIntOrNull() // 编译OK var number2: Int? = string.toIntOrNull() // 也可以这样,自动推断类型为Int? var number3 = string.toIntOrNull() var str1: String = "android" var str2: String? = "Kotlin" // 编译错误 // str1 = null str2 = null// OK // 因为str1不可能为Null,所以不会发生空指针 println(str1.length) // 编译错误,因为str2可空,需要先判断才能访问属性和方法 // println(str2.length) // 先判断非空,再访问str2的属性 var length = if (str2 != null) str2.length else -1 println("str2的长度为:${length}")// -1 // 必须先判断才能访问属性和方法,不然编译错误 if (str2 != null && str2.length > 0) { println(str2.length) } else { println("空字符串") } var booVal: Boolean? = null if (booVal == true) { println(true) } // 条件表达式的结果必须为Boolean型,下面会编译错误 // if (booVal) { // } // 安全调用 var security: String? = "security" println(security?.length)// 输出8 security = null println(security?.length)// 输出null // 安全调用结合let var array: Array<String?> = arrayOf("android,", null, "kotlin,", "ios") for (ele in array) { ele?.let { println(it) }// android,kotlin,ios } var elvisStr: String? = "kotlin" var length1 = if (elvisStr != null) elvisStr.length else -1 println(length1)// 输出6 elvisStr = null // Elvis运算符,简化的if-else // 定义:只要 "?:" 左边的表达式结果为不为null,则返回左边表达式的值,否则返回 "?:" 右边表达式的值 var length2 = elvisStr?.length ?: -1 println(length2)// -1 // 强制调用 !!. 可能会发生空指针异常 var i_val: String? = "100" println(i_val!!.length) i_val = null // println(i_val!!.length)// 空指针异常,编译OK var array2: Array<String?> = arrayOf("android22", null, "kotlin") for (ss in array2) { // ss!!.let { println(it) }// 第二个元素会发生空指针异常 } // 字符串 // 普通字符串 var str11 = "I love kotlin" println(str1[0])// I println(str1[2])// l // 遍历字符串,也可以通过索引获取 for (s in str1) { print(s) } println(str11.length) // 原始字符串, "|"作为边界符,"|"之前的缩进都会去掉 var str22 = """ |I am a programmer, |26 years old, |172cm, |married """.trimMargin() println(str22) var str33 = """ &I am a programmer, &26 years old, &172cm, &married """.trimMargin("&") /** android13 I am a programmer, 26 years old, 172cm, married */ println(str33)// 结果同上 // 字符串模板允许嵌入变量或者表达式 var question = 5 println("第一题得分: ${question}") var intValue = java.util.Random().nextInt(20) + 80 var resultVal = "随机数的值为:${intValue}" println(resultVal) var name = "William" var age = 26 var height = 170 var information = """ |${name} is a programmer, |${age} years old, |${height + 2}cm, |married, |Learn kotlin ${java.util.Random().nextInt(30) + 10} days """.trimMargin() println(information) // Kotlin中的String var str_a = "3.1415926" // var int_str_a: Int = str_a.toInt() // NumberFormatException var d_str_a: Double = str_a.toDouble() var str_b = "314" var int_str_b: Int = str_b.toInt() println("${d_str_a}, ${int_str_b}")//3.1415926, 314 // 首字母大小写 val str_d = "kotlin.kt" println(str_d.capitalize())// 首字母大写 Kotlin.kt println(str_d.decapitalize())// 首字母小写 kotlin.kt // 取相同前缀 println(str_d.commonPrefixWith("kotlin.java"))// kotlin. // 取相同后缀 println(str_d.commonSuffixWith("HelloWorld.kt"))// .kt var str_e = "kotlin666" // 判断str_e是否包含2个连续的数字,正则表达式匹配 println(str_e.contains(Regex("\\d{2}")))// true
package com.william.testkt /** * 类型别名 */ // 为map指定别名 typealias map = HashMap<String, ArrayList<String>> // 为类指定别名 class A { // 内部类InnerA inner class InnerA } class B { // 内部类InnerB inner class InnerB } typealias a_in = A.InnerA typealias b_in = B.InnerB // Kotlin允许为Lambda表达式的类型指定别名, 结果为Boolean型 typealias Filter<T> = (T) -> Boolean fun main(args: Array<String>) { // 直接用别名声明变量 var testMap: map // 直接用a_in和b_in声明变量,调用对象 // 这里的InnerA和InnerB都是内部类 var a: a_in = A().a_in() var b: b_in = B().b_in() val filter: Filter<String> = { it.length > 4 } // 为filter()方法传入参数p,只保留长度大于4的字符串 println(arrayOf("java", "kotlin", "javascript", "oc").filter(filter))// [kotlin, javascript] }
从代码可以看出来,语法和java还是有比较大的区别的:
1.声明变量用var,常量用val。
格式:var | val 变量名 : 类型 或者 var | val 变量名 : 类型?
前者会被映射为java的基本类型,后者会被映射为基本类型的包装类
可以赋初始值,也可以只声明,可以上下文推断。
2.main方法不用在类中声明,因为Kotlin支持函数式编程,也支持面向对象。
后续基础知识会持续补充更新。