Kotlin:变量声明,null安全,条件语句,函数,类与对象

目录

一,变量声明

[1.1 var和val](#1.1 var和val)

[1.2 类型推断](#1.2 类型推断)

[1.3 Null安全](#1.3 Null安全)

[1.3.1 处理可为null性](#1.3.1 处理可为null性)

二,条件语句

2.1条件语句与条件表达式

[2.2 智能类型转换](#2.2 智能类型转换)

三,函数

[3.1 简化函数声明](#3.1 简化函数声明)

[3.2 匿名函数](#3.2 匿名函数)

[3.3 高阶函数](#3.3 高阶函数)

四,类与对象

[4.1 构造函数](#4.1 构造函数)

[4.1.1 主构造函数](#4.1.1 主构造函数)

[4.1.2 次构造函数](#4.1.2 次构造函数)


一,变量声明

1.1 var和val

Kotlin使用两种关键字varval来修饰变量

  • val用于修饰无法被修改的变量,类似于java中的final;
  • var用于修饰可变的变量;
Kotlin 复制代码
//var可变
var a : Int = 1
a = 2

//val不可变
val str : String = "Kotlin"

Kotlin中声明变量时,是先声明变量名称,再声明变量类型。Kotlin的基本数据类型包括BooleanIntFloatLongDouble 等,均为大写开头,与java不同,CharString不属于数值类型,属于一个独立的数据类型;

1.2 类型推断

在Kotlin中,为某个变量赋初值后,Kotlin编译器可根据初始的类型推断变量的类型;

Kotlin 复制代码
//根据"Kotlin"推断str类型为String
val str = "Kotlin"

//String类型方法正常调用
str.toUpperCase()

//其他类型方法不可调用
str.inc()

这里编译器根据"Kotlin"推断变量str类型为String,于是str可以调用String类型的方法,而不可调用Int类型的方法inc;

1.3 Null安全

Kotlin提供了严格的可为null性规则,与java不同,默认情况下,Kotlin变量不可为null值;

Kotlin 复制代码
val str : String = null//不可这样声明,默认情况下不可为null

如果想要使变量可为null,需要在声明变量时在数据类型末尾加上?

Kotlin 复制代码
val str : String? = null

在java中,默认情况下变量是可以为null的,方法的调用者为null时,就会出现空指针异常:NullPointerException

而在Kotlin中,对于这些可为null值的变量,Kotlin提供了多种机制来安全地处理它们;

1.3.1 处理可为null性

(1)使用 **?.**安全调用方法,调用者为null时,返回null,而不是空指针异常;

Kotlin 复制代码
var str3 : String? = null;

//3.1 ?.安全调用方法,调用者为null时,返回null
println(str3?.length); //输出null

(2)使用 **!!.**非null断言运算符,表示告诉编译器方法的调用者绝不为空,但是如果方法的调用者为null,就会报空指针异常,所以这种方法要谨慎使用;

Kotlin 复制代码
var str3 : String? = null

//3.1 !! 非null断言运算符 str3为null时报空指针异常
str3 = "str3非null"
println(str3!!.length) //输出str3非null

str3 = null
println(str3!!.length) //空指针异常

(3)使用 **?:**Elvis运算符,提供一个默认值,在方法调用者为null时,返回默认值;

Kotlin 复制代码
var str3 : String? = null

//3.2 ?: Elvis运算符
val str3Length : Int = str3?.length ?: 0;
println(str3Length) //输出0

二,条件语句

2.1条件语句与条件表达式

Kotlin中同样可以使用if-else语句来处理条件逻辑;

Kotlin 复制代码
if (count == 42) {
    println("I have the answer.")
} else if (count > 35) {
    println("The answer is close.")
} else {
    println("The answer eludes me.")
}

条件表达式:Kotlin条件语句的结果可作为表达式结果返回;

Kotlin 复制代码
var count : Int = 1;

var str4 : String = if(count == 1){
    "hello"
}else if(count == 2){
    "world"
}else{
    "hello world"
};

println(str4); //输出hello

如果你在Kotlin中使用if-else条件表达式,Kotlin会建议你替换为when表达式,当条件语句复杂时,明显when表达式更简洁;

Kotlin 复制代码
count = 3;
str4 = when{
    count == 1 -> "hello"
    count > 2 -> "world"
    else -> "hello world"
};
println(str4); //输出hello world

2.2 智能类型转换

Kotlin的条件语句还可以用来安全处理变量的可为null性,当条件语句判定变量不为null时,我们就不必使用安全调用运算符或非null断言运算符来调用方法;

Kotlin 复制代码
//4.1 智能类型转换
var str6 : String? = "xdyd";
//str6可能为null
println(str6?.length)
//str6一定不会为null
if(str6 != null){
    println(str6.length)
}

三,函数

Kotlin中可以使用函数来封装功能,可以接收参数,声明函数时同样是类型后置;

Kotlin 复制代码
fun getAnswerString(count : Int) : String{
    val ans: String = when{
        count == 1 -> "hello world"
        count < 1 -> "xxx"
        else -> "yyy"
    };
    return ans
}

3.1 简化函数声明

当函数返回单个表达式的值时,可以直接返回条件表达式;

Kotlin 复制代码
fun getAnswerString(count : Int) : String{
    return when{
        count == 1 -> "hello world"
        count < 1 -> "xxx"
        else -> "yyy"
    };
}

也可以将 return 关键字替换为赋值运算符;

Kotlin 复制代码
fun getAnswerString(count : Int) : String = when{
    count == 1 -> "hello world"
    count < 1 -> "xxx"
    else -> "yyy"
}

3.2 匿名函数

在Kotlin中,函数可以没有名称,只通过输入输出来表示,我们称之为匿名函数;

Kotlin 复制代码
val getStringLength = fun (str : String) : Int{
    return str.length
}

匿名函数既可以看作是函数,也可以看作是一个对象,或者说是在把函数当作对象来使用,就像上边我们将匿名函数赋值给了getStringLength变量;

匿名函数也可以通过lambda表达式的方式表示,我们也可以这样理解:getStringLength是一个函数类型的变量,(String)-> Int 就是函数类型,表示接收一个String类型的参数,返回Int类型的值;

Kotlin 复制代码
val getStringLength : (String) -> Int = {
    //参数名称可以自定义,这里为input,就是上面String类型的参数
    input -> input.length
}

匿名函数通常作为高阶函数的参数来使用;

3.3 高阶函数

一个函数可以将另一个函数作为参数来使用,我们称之为高阶函数

Kotlin 复制代码
//5.3 高阶函数 将其他函数作为参数的函数 下面这个函数需要接收一个字符串和一个函数
fun stringMapper(str : String, mapper : (String) -> Int) : Int {
    return mapper(str);
}

//高阶函数的调用,传入了一个字符串和一个(String) -> Int类型的匿名函数
stringMapper("android nb", getStringLength)

val getStringLength : (String) -> Int = {
    input -> input.length
}

当高阶函数的最后一个参数为匿名函数时,匿名函数可以写在圆括号之外;

Kotlin 复制代码
stringMapper("android nb") { input -> input.length }

除了匿名函数之外,高阶函数也可以使用命名函数来作为参数,使用命名函数作为参数时,需使用 **::**来创建函数类型对象,也就是说被 :: 修饰的函数可以作为对象来使用;

Kotlin 复制代码
stringMapper("android nb", ::getMapper)

fun getMapper(str : String) : Int{
    return str.length
}

四,类与对象

Kotlin中同样使用 class来定义类,类中可以包括成员变量,成员方法,构造函数,代码块,内部类等,这些与java都相同,与java不同的是,实例化类时不需要new关键字;

Kotlin 复制代码
//6. 类 构造方法
class Person(){
    //成员变量
    private var name : String = ""

    //成员方法
    fun getName() : Int{
        return name.length
    }

    fun setName(name : String){
        this.name = name
    }

    //内部类
    class man(){

    }
}

//类的实例化
val person : Person = Person()

需要注意的是:在Kotlin中,变量的声明和初始化必须同时进行,如果想要推迟变量的初始化,可以使用 lateinit 关键字修饰;

例如:在使用Android的fragment时;

Kotlin 复制代码
class HomeFragment() : Fragment() {
    //Kotlin必须在声明变量时初始化,使用lateinit可以推迟初始化
    private lateinit var btn_add : Button

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        var view = inflater.inflate(R.layout.item_mine, container, false)
        //初始化
        btn_add = view.findViewById(R.id.btn_mine)
        return view
    }
}

4.1 构造函数

4.1.1 主构造函数

Kotlin中类的主构造函数可以写在类的头部;

Kotlin 复制代码
class Person(var name : String, private var age : Int){
   
}

等同于java代码中这种写法;

java 复制代码
public class Person {
    String name;
    private int age;
    
    public Person(String name, int age){
        this.name = name;
        this.age = age;
    }
}

由于主构造函数不能包含任何代码块,所以我们可以使用初始化程序块来进行一些除初始化之外的操作,初始化程序块使用 init 关键字来修饰;

Kotlin 复制代码
class Person(name : String, age : Int){
    var myName : String
    var myAge : Int

    init{
        myName = name
        myAge = age

        println(myName)
        println(myAge)
    }
}

4.1.2 次构造函数

次构造函数使用 constructor 关键字定义,用于提供多个构造方式。如果需要定义多个构造函数,或者需要一些额外的初始化逻辑,可以使用次构造函数;

如果此构造函数中没有接收全部的成员变量参数,必须给成员变量赋初值;

Kotlin 复制代码
class Person {
    val myName: String
    var myAge: Int

    constructor(name : String){
        myName = name
        myAge = 18
    }

    constructor(name : String, age : Int){
        myName = name
        myAge = age
    }
}

如果类已经定义了主构造函数,那么次构造函数必须显示调用主构造函数;

Kotlin 复制代码
class Person(val name: String, var age: Int) {
    constructor(name: String) : this(name, 0) {
        // 构造逻辑
    }
}

如果你需要定义一个无参构造函数,必须要给给主构造函数的参数提供默认值:

Kotlin 复制代码
class Person(val name: String = "Unknown", var age: Int = 0)

val person = Person() // 使用默认值

可以看出,Kotlin似乎一直在避免一件事:声明的变量没有初始值,或者说声明的变量为null。这也是Kotlin null安全的一角啊;

相关推荐
m0_689087071 小时前
9.26 C++杂项
开发语言·c++
鸽芷咕1 小时前
【Python报错已解决】[notice] A new release of pip available: 22.2 -> 22.2.2
开发语言·python·bug·pip
边疆.1 小时前
C++入门基础 (超详解)
c语言·开发语言·c++
wjs20241 小时前
Scala 字符串
开发语言
jyl_sh2 小时前
CMake教程:第一步:一个基本的起点
开发语言·c++·客户端·cmake
ac-er88882 小时前
php的urlencode和rawurlencode区别
开发语言·php
zyhomepage2 小时前
科技的成就(六十三)
linux·开发语言·人工智能·科技·算法·游戏·内容运营
Envyᥫᩣ2 小时前
深度学习中的卷积神经网络
开发语言
服装学院的IT男2 小时前
【Android 源码分析】Activity生命周期之onPause
android
悟空丶1233 小时前
go基础面试题汇总第一弹
开发语言·后端·golang