内容 :
- 函数、变量、类、属性以及枚举
- Kotlin 中的控制结构
- 智能转换
一 函数声明
fun max(a: Int, b: Int): Int {
return if (a > b) a else b
}函数的声明以关键字 fun 开始,函数名称紧随其后:这个例子中函数名称是 max ,接下来是括号括起来的参数列表。参数列表的后面跟着返回类型,他们之间用冒号隔开。假如没有返回值可以直接不写或者写成Unit类型。
注意:这里return后边代码是表达式而不是语句,表达式有返回值,语句没有返回值。而再Kotlin中基本,除了循环( for, do do/while )以外大多数控制结构都是表达式。
上边函数还可以这样写:
fun max(a: Int, b: Int): Int = if (a > b) a else b如果函数体写在花括号中,我们说这个函数有代码块体。如果它直接返回了个表达式,它就有表达式体。
还可以这样写:
fun max(a: Int, b: Int) = if (a > b) a else b因为Kotlin有类型自动推导特性。
注意:只有表达式体函数的返回类型可以省略。对于有返回值的代码块体函数, 必须显式地写出返回类型和 return 语句。
二 常量和变量
在 Kotlin中以关键字开始,然后是变量名称, 最后可以加上类型(不加也可以)。声明变量的关键字有两个
- val (使用 val 声明的变量不能在初始化之
后再次赋值。它对应的是 Java final 量。)
- var (这种变量的值可以被改变。这种声明对
应的是普通(非 final )的 Java 量。)
如下:
fun ddd() {
//隐式声明局部常量,类型自动推导
val a = 1
//显示声明局部变量
var b: Int = 2
//如果不能提供可以赋给这个常量的值的信息,编译器就无法推断出它的类型,并且val只有一次赋值机会
val c: String
c = "Kotlin就是厉害"
}注意: val 引用自身是不可变的,但是它指向的对象可能是可变的。如下代码完全有效
val array= arrayListOf<String>("1","2","3")
array.add("4")不可变对象和可变对象我们之后再讨论。
注意:编译器只会根据初始化器来推断变量的类型,在决定类型的时候不会考虑 后续的赋值操作。如下错误的写法:
var b: Int = 2
b = "类型错误"三 类
java中的类:
public class Person {
private final String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}使用Kotlin就变成了:
class Person(val name: String)注意:从 Java otlin 的转换过程中 public 修饰符消失了 。在 Kotlin 中,
public 是默认的可见性,所以你能省略它。
四 属性
在类中声明一个属性和声明一个变量一样:使用val和var关键字。声明成val的属性是只读的,而var属性是可变的。当你声明属性的时候,你就声明了对应的get和set方法(只读属性有一个get,而可写属性既有get也有set)如:
class Person {
var name: String = "张三"
val isMan: Boolean = false
}
当你使用这个类的属性时候,内部其实是调用的对应的get和set方法,而是未呈现出来
var p = Person()
//设置值,内部其实是调用了set,只是未呈现
p.name = "张三"
//获取值,内部其实是调用了get,只是未呈现
Log.e("rrrrr",p.name)如果我们去呈现他的get和set方法的就像这样:
class Person {
var name: String = "张三"
get(){
return field
}
set(value) {
field = value
}
val isMan: Boolean = false
get(){
return field
}
}注意:需要解释的是这个field ,你可以把field认为就是name,也可以把field认为是isMan,它的出现就是为了解决死循环,因为默认使用属性,就是调用属性的get方法。
4.2 自定义get和set方法
如创建一个长方形类,里边有一个字段,是判断长方形是否是正方形的标记,我们可以这样写:
class Rect(var w :Int ,var h:Int) {
val isSQ :Boolean
get() {
return w==h
}
}调用:
var rect = Rect(10,10)
Log.e("rrrrrrr","${rect.isSQ}")Log如下:
rrrrrrr: true
4.3 修改属性的可见性
我们可以在自定义的get或者set方法前边加上可见修饰符去修改属性的可见性,访问器的可见性默认与属性的可见性相同。
五 枚举
Kotlin中使用了两个关键字去声明枚举,enum 和 class, enum是一个所谓的软关键字:只有当它出现在class前面时才有特殊的意义,在其他地方可以把它当作普通的名称使用。
enum class Colors() {
//创建枚举对象
Red(),Blue(),Black();
}六 控制语句
6.1 when
when好比java中的switch,比switch强大之处,它也是一个表达式,有返回值,不仅可以传递常量,还可以传递对象。通过上边枚举去选择性返回一个数字,代码如下:
6.1.1传递常量
private fun select(color: Colors): Int {
return when (color) {
Colors.Blue->0
Colors.Black -> 1
Colors.Red -> 2
}
}调用这个方法,传递的参数不同,获取到的返回值也是不同的。上边代码还可以写成这样:
fun select(color: Colors) = when (color) {Colors.Blue->0 ;Colors.Black -> 1 ;Colors.Red -> 2 }6.1.2 传递对象
假设我们有这样一个需求,用代码创建一个调色板,传递一个俩个颜色的set集合对象,返回一个他们的综合色,代码如下:
fun palette(color1: Color, color2: Color): String {
return when (setOf(color1, color2)) {
setOf(Color.Red, Color.Black) -> "蓝色"
setOf(Color.Red, Color.Blue) -> "绿色"
else -> "未知颜色"
}
}注意:
set集合这样写他们是相等的:
val set1 = setOf("1","22")
val set2 = setOf("22","1")
但是这样写他们就是不相等:
val set1 = HashSet<String>()
set1.add("1")
set1.add("22")
val set2 = HashSet<String>()
set1.add("22")
set1.add("1")在java中更是需要自己去循环比较是否相等。
而list集合不管怎么样去创建都是相等的:
var arr1 = ArrayList<String>()
arr1.add("11")
arr1.add("22")
var arr2 = ArrayList<String>()
arr2.add("11")
arr2.add("22")
var arr3 = listOf("11","22")
var arr4 = listOf("11","22")在java中用equals方法判断里边值是否相等
关于更多的集合的比较在后边在去详细说明,这里先记下有这个情况!!!
6.2 if
6.2.1基本用法
上文已经简单的使用了,if的基本用法:
fun max(a: Int, b: Int) = if (a > b) a else b这个表达式体和三元运算符长的很像,因为在Kotlin中if是表达式有返回值 ,所以在Kotlin中没有三元运算符的语法。
在java中类型转换需使用instanceOf , 之后再去向下转型。在kotlin中使用关键字is 判断后,类型会自定转换成你要转换的类型方法。
这里我们去创建一个父亲接口,还有两个儿子类有各种独有的方法:
interface Father
class Son1:Father{ fun son1Method(){} }
class Son2:Father{ fun son2Method(){} }
判断是哪个儿子的方法:
fun who(aaa: Father) {
if (aaa is Son1){
aaa.son1Method()//这里判断是儿子1,只能调用儿子1的方法
}else if (aaa is Son2){
aaa.son2Method()//这里是儿子2,只能调用儿子2的方法
}
}如果想要显示的转换类型就需要使用 as关键字。
6.2.2 if和when之间转换
上边代码判断是哪个儿子的方法,用when重构代码如下:
fun who(aaa: Father) {
when (aaa){
is Son1->aaa.son1Method()
is Son2->aaa.son2Method()
}
}这里更加说明when的强大之处,可以传递常量,对象,甚至是类型判断
6.3 while
6.4 for
6.4.1基础
for (a in 1..100){
}起始值大于结束值用downTo:
for (a in 100 downTo 1){
}每隔两步一循环
for (a in 1..100 step 2 ){
}
for (a in 100 downTo 1 step 2){
}step传递的是绝对值,和正序倒序无关,它会自动判断是每加两步还是每减两步
如果循环区间想写成前闭后开,你可以这样:
for (a in 1 until 100){
}小结:for循环必须使用关键字in ,至于区间可以在 .. 或者downTo 或者until之间最少选择一个,step表示步长,和正负无关。
6.4.2循环map
循环map还是和java中有区别的,在java中循环map需要去通过键获取值,而在kotlin中你可以一次全部循环处理,代码可以这样写:
val map = TreeMap<String,String>()
map.put("1","1.1")
for ((key,value) in map) {
Log.e("rrrr","key${key}===value${value}")
}这使你更加容易去取到map中的值。
6.4.3循环arraylist:
val arr = arrayListOf("1","2")
//正常循环和java并无异样
for (value in arr){
Log.e("rrr","value${value}")
}
//使用withIndex 循环,是循环带有下边的list集合
for ((index ,value) in arr.withIndex()){
Log.e("rrr","value${value}index${index}")
}6.4.4 in关键字能用到哪些控制结构中
上边循环for中使用了in。同时在if中也能用in使用in运算符来检查一个值是否在区间中,或者它的逆运算,!n,来检查这个值是否不在区间中。
val arr = arrayListOf("1","2")
if ("1" !in arr){
}而且在when中也能使用in,代码和使用is是一样的。
小结:
- 方法声明的结构,以及表达式体和代码块体。
- 常量和比变量的声明,数组不变,数组里内容可变
- 类型自动推导的便捷使用。
- 类的声明,以及关键字class
- 属性的声明以及重写get和set方法
- 枚举的声明格式,软关键字menu
- when控制结构,可以传递常量,对象,甚至可以使用is或者in关键字
- if控制结构,使用关键字is ,in, .. , downTo ,step ,until
- for控制结果,使用关键字 in, .. , downTo ,step ,until,循环map和循环带下表的arraylist集合