它是一种针对 java 平台的新编程语言,Kotlin 简洁、安全、务实,Kotlin可以运行在 任何 java 运行的地方,并且能够和 java语言无缝对接上。
kotlin语言和java语言一样,都是静态语言
//java 语言编译流程
.java -> java编译器 -> .class -> jvm执行
//kotlin 语言编译流程
.kt ->kotlin编译器 -> .class -> jvm执行
很多插件都提供了转换器 ,java 转 Kotlin
// hello world
//使用 fun 关键字声明一个函数,参数类型写在后面
fun main(args: Array<String>) {
//kt 标准库打印方法
println("Hello, world!") //结尾不需要;
}
在kt中,if 是表达式,而不是语句。语句和表达式的区别在于,表达式有值,并且能作为另一个表达式的一部分使用;而语句总是包围着它的代码块中的顶层元素,并且没有自己的值,在java中所有的控制结构都是语句。而在kt中除了for 、do while、while以外大多数控制结构都是表达式
//常规函数写法
fun max(a:Int,b:Int):Int{
//在 Koltin 语言中 if 不是语句,而是表达式
// if(a>b) a else b 相当于java中的三目运算符,在kt中并没有三目运算符
return if(a>b) a else b
}
//表达式函数 (其实就是简写)
fun max(a:Int,b:Int):Int = if(a>b) a else b
//再简写 返回类型省略。kt编译器自动进行类型推导
fun max(a:Int,b:Int) =if(a>b> a else b
在java中声明一个变量前面必须带有这个变量的类型声明,而在kt中不需要这么做,在kt中用关键字 var、val 关键这声明一个变量。var 声明的变量是可变的,val声明的是不可变的。kt 编译器自动进行类型推导。
val s ="abc";
var i = 12;
i =13;
val i2 = 1;
i2 =12;//错误,不可改变
var i3 = "a";
i3 =1;//错误,类型不匹配
//也可指定类型
val a:Int = 1;
// la 引用不可改变, 改变引用的对象。可以这样做
val la = arrayListOf("java")
// 改变引用的对象
la.add("kt")
//在定义了val变量的代码块执行期间,val变量只能进行一次唯一初始化。
//kt 编译器更智能了,如果kt编译器能确保只有唯一一条初始化语句会被执行,可以根据条件进行初始化,在java语言上用final是不允许这样做的。
val msg:String
if(isSuccess()){
msg = "success"
}else {
msg ="failed"
}
更简单字符串格式化,字符串模板。
val s ="hello kt";
//打印s对象 等价于java中的 s+"-"+s
println("$s - $s");
//打印 $S符号
println("\$");
//高级一点的用法,有点像jsp
fun main(args: Array){
println("hello, ${args[0]}");
}
类和属性
//声明一个bean,有一个name属性
package cn.hellormrhuang
//kt中默认public
class Person(val name:String)
----------
//在kt中使用
fun main(args: Array){
//不需要 new
val person = Person("huangbao");
val name =person.name;
println("$name");
}
----------
//java中使用
Person person =new Person("huangbao");
person.getName();
----------
package host.kotlin_hello
//自定义访问器
//属性有要一个对应的字段保存数据,在一些需要即时计算的场景中可以使用自定义访问器
class Rect(val width:Int,val height:Int){
val isSquare:Boolean
get(){
return width == height
}
//简洁写法
// get() = width == height
}
fun main(args:Array){
//使用
val rect = Rect(10,10)
rect.isSquare
}
kt源码目录:源码和包
//和java一样也有相似的包概念,但是kt并没有对磁盘源文件做限制
package host.kotlin_hello
when 表达式
package host.kotlin_hello
/**
* 声明枚举
*/
enum class Color(val r:Int,val g:Int ,val b:Int){
RED(255,0,0),ORANGE(255,165,0),YELLOW(255,0,0);//唯一需要;的地方
//枚举方法
fun rgb() = (r*256+g)*256+b
}
fun main(args:Array){
println(Color.YELLOW.rgb())
}
/**
*直接返回一个when表达式
*/
fun get(color:Color)=
// when 和java中的switch相似。但是when更强大,when是一个表达式,并且不需要break结束;
when(color){
Color.RED -> "red"
Color.ORANGE-> "of"
Color.YELLOW ->"york"
}
/**
*多个值合并到分支上
*/
fun get2(color:Color)= when(color){
Color.RED, Color.ORANGE-> "of"
Color.YELLOW ->"york"
}
/**
* when 结构中能使用任意对像,java中switch要求必须是常量(枚举常量、字符串常量或数字面值)
* setOf ,创建一个Set集合
*/
fun mix(colorA:Color,colorB:Color) = when(setOf(colorA,colorB)){
setOf(Color.RED,Color.YELLOW) ->"red"
setOf(Color.ORANGE,Color.YELLOW)->"yellow"
else -> throw Exception("dirty color")
}
/**
* 使用不带参数的 when
* setOf ,创建一个Set集合
*/
fun mix2(colorA:Color,colorB:Color) =when{
(colorA == Color.RED &&colorB ==Color.YELLOW
||colorB == Color.RED &&colorA ==Color.YELLOW
)->"red"
else -> throw Exception("dirty color")
}
/**
* 智能转换
* 在kt中用is检查来判断一个变量是否是某种类型。相当于java中的instanceOf
* 使用is检查后不需要再强制转换成相对应的类型了,这个工作kt编译器帮我们做了
*/
fun sample(){
var color = Color.RED
if(color is Color){
//直接将 color 当前 Color类型
//todo
}
//转换
val c = color as Color
//todo
}
* kt 中改造了java中的for(int i =0;i<10,i++){}这种方式,使用了区间的概念 *
package cn.hellormrhuang
fun main(args: Array){
//表示1到100区间
val a = 1..100
for(i in a){
//打印 1到100
print("$i");
}
println("---------");
for(i in 100 downTo 1 ){
//打印 100 到 1
print("$i");
}
println("---------");
//步长为2
for(i in 100 downTo 1 step 2 ){
//打印 100 到 1 ,100 ,98 96
print("$i");
}
println("---------");
for(x in 0 until 100 ){
//打印1 到 99
print("$x ");
}
}
迭代集合
//迭代 map
val treeMap = TreeMap()
for (c in 'A'..'F'){
val binary = Integer.toBinaryString(c.toInt())
treeMap[c] = binary
}
for ((a,b) in treeMap){
println("$a = $b")
}
//迭代 list
val list = arrayListOf("a", "b", "c")
for ((index,element) in list.withIndex()){
println("$index = $element")
}
使用in和!in检查集合和区间的成员
fun isLetter(c:Char) = c in 'a'..'z' || c in 'A' .. 'Z'
kt中创建集合,kt使用的是java中的标准集合类
//kt中创建集合
val hashSetOf = hashSetOf("a", "b", "c")
//等价于java getClass()
println(hashSetOf.javaClass)
val map = hashMapOf(1 to "one",2 to "two")
val listOf =listOf(1,2,3)
//相当于调用java中的toString()方法
println(listOf)
让函数更好的调用
/**
* 不需要重载了。参数可以有默认值
*
*/
fun joinString(collection: Collection,
prefix:String="[",
postfix:String="]"
){
//todo
}
fun main(args:Array){
val list = listOf("a")
joinString(list)
//还可以这样
joinString(list,prefix=",",postfix = "1")
}
消除静态工具类:顶层函数和顶层属性
Test3.kt文件
//指定类名
@file:JvmName("test3_fun")
package host.kotlin_hello
/**
* 类
*/
class Stu{
}
/**
* 在kt中可以将函数或属性声明在class的外面。称为顶层函数和顶层属性
*
*/
var count =0
fun get(){
count++
}
fun main(args:Array){
// kt中直接调用
get()
}
----------
//java中调用
//Test3Kt.get();
test3_fun.get();
### 给别人的类添加方法:扩展函数和属性 ###
//Test4Kt.kt源文件
package host.kotlin_hello
//需要导入扩展函数
import host.kotlin_hello.lastChar
//重命名扩展函数
import host.kotlin_hello.lastChar as last
/**
*定义一个String类的扩展函数
*
* String.xx ->接收者类型
* this.xx ->接收者对象
*
* 本质:
* 本质上是扩展函数是一个静态函数,它把调用它的对象修为了它的一个参数。
* 调用扩展函数不会创建适配的对象或者任何运行时的额外消耗
*/
fun String.lastChar():Char = this.get(this.length-1)
fun main(args:Array){
//可以像调用普通类成员函数进行调用
val str ="kotlin".lastChar()
val lastChar = "java".lastChar()
}
######
//java中调用
//本质是静态函数
abc = Test4Kt.lastChar("abc");
######
/**
* 扩展属性
* 声明一个扩展属性
* */
val String.lastChar:Char
get() = get(length-1)
可变参数、中缀调用、解构声明
/**
* 可变参数
*/
fun fetch(vararg values:T){
}
/**
* 键值对的处理:中缀调用和解构声明
* to是特殊的函数调用,称为中缀调用
* 1 to "one" <--> 1 to ("one")
* 中缀调用可以和只能一个参数的函数使用,无论是普通函数还是扩展函数。要允许使用中缀符号调用函数,需要infi修饰符来
* 标记它。
*/
fun fetch2(){
val maps = mapOf(1 to "one",2 to "two")
//下面是一个函数的to函数声明,Pair是kt中标准库中的一个类
infix fun Any.to(other:Any) = Pair(this,other)
//可以直接用Pair的内容来初始化变量 , 这个功能被称为解构声明
val (number,name) = 1 to "one"
}
局部函数
package host.kotlin_hello.kotlin1
/**
* 局部函数。可以解决常见的代码重复问题
*/
class User(val id:Int,val name:String,val address:String)
fun saveUser(user:User){
//重复代码
if(user.name.isEmpty()){
throw IllegalArgumentException("Can't save user ${user.id}:empty name")
}
//重复代码
if(user.address.isEmpty()){
throw IllegalArgumentException("Can't save user ${user.id}:empty address")
}
//保存
}
fun saveUser2(user:User){
//局部函数。还能这样玩...
fun validate(user: User,value:String,fieldName:String){
if(value.isEmpty()){
throw IllegalArgumentException("Can't save user ${user.id}:empty ${fieldName}")
}
}
validate(user,user.name,"name")
validate(user,user.address,"address")
//保存
}
fun saveUser3(user:User){
//局部函数可以访问所在函数的变量
fun validate(value:String,fieldName:String){
if(value.isEmpty()){
throw IllegalArgumentException("Can't save user ${user.id}:empty ${fieldName}")
}
}
validate(user.name,"name")
validate(user.address,"address")
//保存
}
/*
* 将校验方法放在扩展函数中
* */
fun User.validateBeForeSave(){
fun validate(value:String,fieldName:String){
if(value.isEmpty()){
throw IllegalArgumentException("Can't save user ${id}:empty ${fieldName}")
}
}
validate(name,"name")
validate(address,"address")
}
fun saveUser4(user:User){
user.validateBeForeSave()
//保存
}