完整代码Gitee地址:kotlin-demo: Kotlin学习代码
第一天学习内容代码:Chapter1类
创建一个LearnKotlin.kt类
知识点1:日志输出
fun main() {
//1、日志打印
println("日志输出")
???????}
点run执行结果
知识点2:变量声明 val、var
fun main() {
//2、val声明一个不可变变量 对应java的final
//var声明一个可变变量 好的代码习惯,优先使用val
val a = 10
val b = 37
???????}
知识点3:定义函数、语法糖
fun main() {
//3、定义函数
val a = 10
val b = 37
println("methodName = " + methodName(a, b))
//函数的语法糖写法
fun methodName(param1: Int, param2: Int) = max(param1, param2)
println("methodName = " + methodName(a, 20))
???????}
//fun(function的简写)是定义函数的关键字
//fun后面的是函数名
//函数名后面紧跟着一对括号,里面可以声明该函数接收什么参数,参数的数量可以是任意多个
//参数括号后面的那部分是可选的,用于声明该函数会返回什么类型的数据
fun methodName(param1: Int, param2: Int): Int {
//返回两个参数中更大的那个数
return max(param1, param2)
}
打印日志结果为:?
知识点4:条件语句 if、where
????????Kotlin中的条件语句主要有两种实现方式:if和when。
? ? ? ? 如果你熟悉Java的话,应该知道Java中的switch语句并不怎么好用。首先,switch只能传入整型或短于整型的变量作为条件,JDK 1.7之后增加了对字符串变量的支持,但如果你的判断逻辑使用的并非是上述几种类型的变量,那么不好意思,switch并不适合你。其次,switch中的每个case条件都要在最后主动加上一个break,否则执行完当前case之后会依次执行下面的case,这一特性曾经导致过无数奇怪的bug,就是因为有人忘记添加break。
? ? ? ? 而Kotlin中的when语句不仅解决了上述痛点,还增加了许多更为强大的新特性,有时候它比if语句还要简单好用,现在我们就来学习一下吧
fun main() {
//4、条件语句 if、where
conditional()
???????}
//4、条件语句
fun conditional() {
//用if判断二个函数的较大值
println("ifMethodName = " + ifMethodName(20, 50))
//语法糖写法
fun ifMethodName1(num1: Int, num2: Int) =
if (num1 > num2) {
num1
} else {
num2
}
//语法糖再精简
fun ifMethodName(num1: Int, num2: Int) = if (num1 > num2) num1 else num2 * 2
println("ifMethodName = " + ifMethodName(15, 35))
//用where判断成绩,与Java相比不用写break,且是有返回值的可精简为
fun whenStudent(name: String) =
when (name) {
"Peace" -> 60
"Jay" -> 72
"what" -> 80
else -> 0
}
println("ifStudent = " + whenStudent("Jay"))
//用where判断参数类型
fun whenType(num: Number) =
when (num) {
is Int -> println("is Int")
is Double -> println("is Double")
is Long -> println("is Long")
is Float -> println("is Float")
is Short -> println("is Short")
else -> println("else")
}
whenType(1234567890987654321)
//如果我们不在when语句中传入参数的话,还可以这么写
//举个例子,假设所有名字以Pea开头的人,他的分数都是90分,这种场景如果用带参数的when语句来写就无法实现
fun whenStu(name: String) = when {
name.startsWith("Pea") -> 90
name == "Peace" -> 60
name == "Jay" -> 72
name == "what" -> 80
else -> 0
}
println("whenStu = " + whenStu("Peace"))
}
//用if判断二个函数的较大值
fun ifMethodName(num1: Int, num2: Int): Int {
// var value = 0
// if (num1 > num2) {
// value = num1
// } else{
// value = num2
// }
//if是有返回值的,可以简化为
return if (num1 > num2) {
num1
} else {
num2
}
}
?打印日志结果为:?
知识点5:循环语句 for 、代码区间
????????Kotlin在for循环方面做了很大幅度的修改,Java中最常用的for-i循环在Kotlin中直接被舍弃了,而Java中另一种for-each循环则被Kotlin进行了大幅度的加强,变成了for-in循环,所以我们只需要学习for-in循环的用法就可以了
????????val value = 0..10,这种语法结构看上去挺奇怪的吧?但在Kotlin中,它是完全合法的。上述代码表示创建了一个0到10的区间,并且两端都是闭区间,这意味着0到10这两个端点都是包含在区间中的,用数学的方式表达出来就是[0, 10]。
????????Kotlin中可以使用until关键字来创建一个左闭右开的区间,使用step跳过区间内的元素,使用downTo遍历降序区间。
fun main() {
//5、循环语句 for
loopInfo()
???????}
//5、循环语句 for
fun loopInfo() {
//使用for-in遍历区间
val value = 0..10
for (i in value) {
print(" $i")
}
//双端闭区间不如单端闭区间好用,相信你一定知道数组的下标都是从0开始的,
//一个长度为10的数组,它的下标区间范围是0到9,因此左闭右开的区间在程序设计当中更加常用。
//Kotlin中可以使用until关键字来创建一个左闭右开的区间
//使用until替代..关键字,就不会打印10
println(" ")
val range = 0 until 10
for (i in range) {
print(" $i")
}
//如果想跳过其中的一些元素,可以使用step关键字
//上述代码表示在遍历[0, 10)这个区间的时候,每次执行循环都会在区间范围内递增2,
//相当于for-i循环中i = i + 2的效果
println(" ")
for (i in range step 2){
print(" $i")
}
//前面的..和until关键字都要求区间的左端必须小于等于区间的右端,
//也就是这两种关键字创建的都是一个升序的区间。
//如果你想创建一个降序的区间,可以使用downTo关键字
println(" ")
for (i in 10 downTo 0){
print(" $i")
}
println(" ")
}
?打印日志结果为:?
知识点6:面向对象
????????不同于面向过程的语言(比如C语言),面向对象的语言是可以创建类的。类就是对事物的一种封装,比如说人、汽车、房屋、书等任何事物,我们都可以将它封装一个类,类名通常是名词。而类中又可以拥有自己的字段和函数,字段表示该类所拥有的属性,比如说人可以有姓名和年龄,汽车可以有品牌和价格,这些就属于类中的字段,字段名通常也是名词。而函数则表示该类可以有哪些行为,比如说人可以吃饭和睡觉,汽车可以驾驶和保养等,函数名通常是动词。
fun main() {
//6、面向对象
objectView()
???????}
//6、面向对象
fun objectView() {
//拥有了3种方式来对StudentModel类进行实体化,
//分别是通过不带参数的构造函数、通过带两个参数的构造函数、通过带4个参数的构造函数
val student1 = StudentModel()
val student2 = StudentModel("周润发",28)
val student3 = StudentModel("111222",3,"周润发",28)
//类中只有次构造函数,没有主构造函数写法
val student = StudentModel1("333444",6,"刘德华",18)
}
创建StudentModel数据模型
/**
* Created by: PeaceJay
* Created date: 2021/10/25
* Description: 学生信息模型
*/
//继承了PersonModel的姓名与年龄
//sno学号 grade年级 name姓名 age年龄
class StudentModel(sno: String, grade: Int, name: String, age: Int) : PersonModel(name, age) {
//主构造函数没有函数体,如果我想在主构造函数中编写一些逻辑,该怎么办呢?
//Kotlin给我们提供了一个init结构体
init {
println("sno=$sno, grade=$grade,name=$name,age$age")
}
//次构造函数是通过constructor关键字来定义的,通过this关键字调用了主构造函数
//第一个次构造函数接收name和age参数,然后它又通过this关键字调用了主构造函数,并将sno和grade这两个参数赋值成初始值
constructor(name: String, age: Int) : this("", 0, name, age) {
}
//第二个次构造函数不接收任何参数,它通过this关键字调用了我们刚才定义的第一个次构造函数,
//并将name和age参数也赋值成初始值,由于第二个次构造函数间接调用了主构造函数,因此这仍然是合法的
constructor() : this("", 0) {
}
}
类中只有次构造函数,没有主构造函数写法
//首先Student类的后面没有显式地定义主构造函数,同时又因为定义了次构造函数,
//所以现在Student类是没有主构造函数的。那么既然没有主构造函数,
//继承Person类的时候也就不需要再加上括号了
class StudentModel1 : PersonModel {
constructor(sno: String, grade: Int,name: String, age: Int) : super(name, age) {
println("sno=$sno, grade=$grade,name=$name,age$age")
}
}
?打印日志结果为:?
知识点7:接口、函数修饰符
????????Kotlin中的接口部分和Java几乎是完全一致的。接口是用于实现多态编程的重要组成部分。我们都知道,Java是单继承结构的语言,任何一个类最多只能继承一个父类,但是却可以实现任意多个接口,Kotlin也是如此。
????????我们可以在接口中定义一系列的抽象行为,然后由具体的类去实现。下面还是通过具体的代码来学习一下,首先创建一个Study接口,并在其中定义几个学习行为。
/**
* Created by: PeaceJay
* Created date: 2021/10/25
* Description: 定义学生接口
*/
interface Study {
//在Study接口中添加几个学习相关的函数
fun readBooks()
fun doHomeWork()
//我们给doHomework()函数加上了函数体,并且在里面打印了一行日志。
//如果接口中的一个函数拥有了函数体,这个函数体中的内容就是它的默认实现。
//现在当一个类去实现Study接口时,只会强制要求实现readBooks()/doHomeWork()函数,
//而newDoHomeWork()函数则可以自由选择实现或者不实现,不实现时就会自动使用默认的实现逻辑
fun newDoHomeWork(){
println("newDoHomeWork")
}
}
接下来就可以让StudentBean类去实现Study接口了?
//Java中继承使用的关键字是extends,实现接口使用的关键字是implements,
//而Kotlin中统一使用冒号,中间用逗号进行分隔
//必须加var否则无法引用
class StudentBean(var name: String, age: Int) : PersonModel(name, age), Study {
override fun readBooks() {
println("$name is readBooks")
}
override fun doHomeWork() {
println("$name is doHomeWork")
}
}
??现在我们可以在main()函数中编写如下代码来调用这两个接口中的函数
fun main() {
//7、接口
interfaceView()
???????}
//7、接口
//接口是用于实现多态编程的重要组成部分。我们都知道,Java是单继承结构的语言,
//任何一个类最多只能继承一个父类,但是却可以实现任意多个接口,Kotlin也是如此
fun interfaceView() {
val student = StudentBean("刘德华",18)
doStudy(student)
}
//演示一下多态编程的特性
fun doStudy(student: StudentBean) {
student.readBooks()
student.doHomeWork()
student.newDoHomeWork()
}
?打印日志结果为:??
了解函数的可见性修饰符
????????Java中有public、private、protected和default(什么都不写)这4种函数可见性修饰符 Kotlin中也有4种,分别是public、private、protected和internal; ????????private:private修饰符在两种语言中的作用是一模一样的,都表示只对当前类内部可见 ????????public:public修饰符的作用虽然也是一致的,表示对所有类都可见,但是在Kotlin中public修饰符是默认项,而在Java中default才是默认项; ????????protected:protected关键字在Java中表示对当前类、子类和同一包路径下的类可见,在Kotlin中则表示只对当前类和子类可见; ????????default:Kotlin抛弃了Java中的default可见性(同一包路径下的类可见),引入了一种新的可见性概念,只对同一模块中的类可见,使用的是internal修饰符。比如我们开发了一个模块给别人使用,但是有一些函数只允许在模块内部调用,不想暴露给外部,就可以将这些函数声明成internal;
知识点8:数据类(数据模型)
????????数据类通常占据着非常重要的角色,它们用于将服务器端或数据库中的数据映射到内存中,为编程逻辑提供数据模型的支持。或许你听说过MVC、MVP、MVVM之类的架构模式,不管是哪一种架构模式,其中的M指的就是数据类。
????????数据类通常需要重写equals()、hashCode()、toString()这几个方法。其中,equals()方法用于判断两个数据类是否相等。hashCode()方法作为equals()的配套方法,也需要一起重写,否则会导致HashMap、HashSet等hash相关的系统类无法正常工作。toString()方法用于提供更清晰的输入日志,否则一个数据类默认打印出来的就是一行内存地址。
????????这里我们新构建一个手机数据类,字段就简单一点,只有品牌和价格这两个字段。如果使用Java来实现这样一个数据类,代码就需要这样写:
/**
* Created by: PeaceJay
* Created date: 2021/10/25
* Description:
*/
//Java版本写法
//数据类通常需要重写get()/set()、equals()、hashCode()、toString()这几个方法
public class Cellphone {
private String brand;
private double price;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public Cellphone(String brand, double price) {
this.brand = brand;
this.price = price;
}
//toString()方法用于提供更清晰的输入日志,否则一个数据类默认打印出来的就是一行内存地址
@NotNull
@Override
public String toString() {
return "Cellphone{" +
"brand='" + brand + '\'' +
", price=" + price +
'}';
}
//equals()方法用于判断两个数据类是否相等
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Cellphone cellphone = (Cellphone) o;
return Double.compare(cellphone.price, price) == 0 &&
Objects.equals(brand, cellphone.brand);
}
//hashCode()方法作为equals()的配套方法,也需要一起重写,否则会导致HashMap、HashSet等hash相关的系统类无法正常工作
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
public int hashCode() {
return Objects.hash(brand, price);
}
}
Java的写法就显得比较复杂了,来试试Kotlin:
/**
* Created by: PeaceJay
* Created date: 2021/10/25
* Description:
*/
//你没看错,只需要一行代码就可以实现了!
//神奇的地方就在于data这个关键字,当在一个类前面声明了data关键字时,
//就表明你希望这个类是一个数据类,Kotlin会根据主构造函数中的参数帮你将equals()、hashCode()、toString()等,
//固定且无实际逻辑意义的方法自动生成,从而大大减少了开发的工作量。
data class CellphoneKt(val brand: String, val price: Double) {
init {
println("brand=$brand" + "price=$price")
}
}
????????只需要一行代码就可以实现了!就在于data这个关键字,当在一个类前面声明了data关键字时,就表明你希望这个类是一个数据类。
????????下面我们来测试一下这个数据类,在main()函数中编写如下代码:
fun main() {
//8、数据类
dataView()
???????}
//8、数据类
fun dataView() {
//在一个规范的系统架构中,数据类通常占据着非常重要的角色,
//它们用于将服务器端或数据库中的数据映射到内存中,为编程逻辑提供数据模型的支持。
//或许你听说过MVC、MVP、MVVM之类的架构模式,不管是哪一种架构模式,其中的M指的就是数据类
//下面我们来测试一下这个数据类
val cellphoneKt1 = CellphoneKt("小米11 12+256",4299.00)
val cellphoneKt2 = CellphoneKt("红米K40 Pro+ 12+256",3699.00)
val cellphoneKt3 = CellphoneKt("红米K40 Pro+ 12+256",3699.00)
println(cellphoneKt1)
println("cellphoneKt2 equals cellphoneKt3 = " + (cellphoneKt2 == cellphoneKt3))
}
?打印日志结果为:
知识点9:单例类
? ? ? ? 单例模式做为最常用、最基础的设计模式之一,它可以用于避免创建重复的对象,来看看Java版本:
/**
* Created by: PeaceJay
* Created date: 2021/10/25
* Description: Java写法单例
*/
public class Singleton {
//这段代码其实很好理解,首先为了禁止外部创建Singleton的实例,
//我们需要用private关键字将Singleton的构造函数私有化,
//然后给外部提供了一个getInstance()静态方法用于获取Singleton的实例。
//在getInstance()方法中,我们判断如果当前缓存的Singleton实例为null,
//就创建一个新的实例,否则直接返回缓存的实例即可,这就是单例模式的工作机制
private static Singleton instance;
private Singleton() {
}
public synchronized static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
public void SingletonText(){
System.out.println("SingletonText");
}
}
?调用单例类中的方法:
//调用单例类中的方法
Singleton singleton = new Singleton.getInstance();
singleton.SingletonText();
????????虽然Java中的单例实现并不复杂,但是Kotlin明显做得更好,它同样是将一些固定的、重复的逻辑实现隐藏了起来,只暴露给我们最简单方便的用法。在Kotlin中创建一个单例类的方式极其简单,只需要将class关键字改成object关键字即可。现在我们尝试创建一个Kotlin版的Singleton单例类:
/**
* Created by: PeaceJay
* Created date: 2021/10/25
* Description:
*/
//在Kotlin中创建一个单例类的方式极其简单,只需要将class关键字改成object关键字即可
object SingletonKt {
fun singletonText() {
println("is singletonText")
}
}
?在main()函数中编写如下代码:
fun main() {
//9、单例类
singletonView()
???????}
//9、单例类
fun singletonView() {
SingletonKt.singletonText()
}
?打印日志结果为:?
?学习参考:第一行代码——Android(第3版)第二章节
|