kotlin笔记第二篇
1.声明的变量,如果有构造器的话,可以不用第一时间初始化
class User {
val name: String
val id: Int
//默认public
constructor(name: String, id: Int) {
this.name = name
this.id = id
}
}
2.初始化代码块用init
class User {
//初始化代码块,优先于构造器执行
init {
}
val name: String
val id: Int
//默认public,在初始化代码块init之后执行
constructor(name: String, id: Int) {
this.name = name
this.id = id
}
}
3.final
的使用
java
的final
和kotlin
中的val
类似,区别在于Kotlin
函数参数默认是 val
类型,且val
变量的get
函数可改动
fun method(message: String) {
message = "asdf" //会报错
}
4.val
修饰的变量不能再次赋值,但是可以修改get
方法,
val id: Int
//每次获取id值,都会x10
get() {
return field * 10
}
5.static
、object
关键字
java里通常定义静态常量如下
public static final int MAX_SIZE = 100;
kotlin里定义静态常量如下,使用object
,注意:是小写,不同于java
的Object
,java
的Object
在kotlin
里是Any
class User {
//使用 companion object
companion object {
const val MAX_SIZE: Int = 100
}
}
用 object
修饰的对象中的变量
和函数
都是静态
的,用object
修饰的类就是单例,简单说就是
object 其实是把两步合并成了一步,既有 class 关键字的功能,又实现了单例
单例类(饿汉式的单例,并且实现了线程安全)
object A {
val number: Int = 1
fun method() {
println("A.method()")
}
}
object
还可以创建匿名类
6.companion
关键字
companion 可以理解为伴随、伴生,表示修饰的对象和外部类绑定
一个类里,部分属性是静态的,部分不是,如下:
class A {
//没有object修饰的不是静态的
val age = 10
//有companion的是伴生对象,一个类只能有一个伴对象,B可以省略
//可以直接A.MAX_SIZE
companion object B {
val MAX_SIZE: Int = 100
}
//其他object修饰的是嵌套对象,可以有多个
//引用只能A.C.MIN_SIZE
object C {
val MIN_SIZE: Int = 50
}
}
1.将属性或者函数
的声明放在class
之外,如下
package com.kotlinpractice.kotlin
val GLOBAL_AGE: Int = 10
fun globalGetScreenHeight(): Int {
return 0
}
class Util {
//类内部
}
引用的时候可以直接全局引用:
open class KotlinTestActivity : AppCompatActivity(), Impl {
final override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//可以直接引用
GLOBAL_AGE
globalGetScreenHeight()
}
}
这样的属性和函数不属于任何class
,直接属于package
不同包下的顶级函数,名字可以相同,使用的时候会自动导入不同的包名区分
顶层声明的一般用于工具类等
java
定义常量
public static final int MAX_SIZE = 100;
kotlin
定义常量
class A {
//伴生对象的常量 加上 const
companion object B {
const val MAX_SIZE: Int = 100
}
//嵌套对象的常量 加上 const
object C {
const val MIN_SIZE: Int = 50
}
}
Kotlin 的常量必须声明在对象(包括伴生对象)或者「top-level 顶层」中,因为常量是静态的。
Kotlin 中只有基本类型和 String 类型可以声明成常量。
上一节的基本数据类型介绍中有IntArray
,使用intArrayOf()
函数如下
//类型都可以省略,kotlin自动推断
var number: Int = 10//还有Double Float Long Short Byte
var char: Char = 'c'
var isFood: Boolean = true
var ages: IntArray = intArrayOf(1, 2, 3)//FloatArray DoubleArray CharArray
var str: String = "Lili"
声明一个数组,
//类型都可以省略,kotlin自动推断
var number: Int = 10//还有Double Float Long Short Byte
var char: Char = 'c'
var isFood: Boolean = true
var ages: IntArray = intArrayOf(1, 2, 3)//FloatArray DoubleArray CharArray
var str: String = "Lili"
//声明数组,对象类型,使用arrayOf()函数
var strs: Array<String> = arrayOf("a", "b", "c")
调用同java,直接去下标
fun testArray() {
strs[1] = "B"
}
1.list
,使用listOf
函数
//类型都可以省略,kotlin自动推断
var number: Int = 10//还有Double Float Long Short Byte
var char: Char = 'c'
var isFood: Boolean = true
var ages: IntArray = intArrayOf(1, 2, 3)//FloatArray DoubleArray CharArray
var str: String = "Lili"
//声明数组,对象类型,使用arrayOf()函数
var strs: Array<String> = arrayOf("a", "b", "c")//不支持协变
//声明list,对象类型,使用listOf()函数
var strList: List<String> = listOf("a", "b", "c")//支持协变
协变就是子类对象赋值给父类对象
数组
和list
对比,使用基本数据类型
的时候,还是用数组
更好一些,不用装箱
2.set
,使用setOf
函数
//类型都可以省略,kotlin自动推断
var number: Int = 10//还有Double Float Long Short Byte
var char: Char = 'c'
var isFood: Boolean = true
var ages: IntArray = intArrayOf(1, 2, 3)//FloatArray DoubleArray CharArray
var str: String = "Lili"
//声明数组,对象类型,使用arrayOf()函数
var strs: Array<String> = arrayOf("a", "b", "c")//不支持协变
//声明list,对象类型,使用listOf()函数
var strList: List<String> = listOf("a", "b", "c")//支持协变
//声明set,对象类型,使用setOf()函数
var strSet: Set<String> = setOf("a", "b", "c")//支持协变
3.map
,使用mapOf
函数
//类型都可以省略,kotlin自动推断
var number: Int = 10//还有Double Float Long Short Byte
var char: Char = 'c'
var isFood: Boolean = true
var ages: IntArray = intArrayOf(1, 2, 3)//FloatArray DoubleArray CharArray
var str: String = "Lili"
//声明数组,对象类型,使用arrayOf()函数
var strs: Array<String> = arrayOf("a", "b", "c")//不支持协变
//声明list,对象类型,使用listOf()函数
var strList: List<String> = listOf("a", "b", "c")//支持协变
//声明set,对象类型,使用setOf()函数
var strSet: Set<String> = setOf("a", "b", "c")//支持协变
//声明map
var map: Map<Int, String> = mapOf(1 to "a", 2 to "b", 3 to "c")
调用,取值
fun testArray() {
strs[1] = "B"
//map取值,都可以,编辑器推荐用第二种
val value1 = map.get(1)
val value2 = map[2]
}
赋值,则不能使用mapOf
创建的map
集合,需要使用mutableMapOf
创建的集合,
添加代码:
var mapChange: MutableMap<Int, String> = mutableMapOf(1 to "a", 2 to "b", 3 to "c")
即可更改map
值
fun testArray() {
strs[1] = "B"
//map取值
val value1 = map.get(1)
val value2 = map[2]
//可改值的map赋值
mapChange.put(1, "A")
mapChange[1] = "A"
}
同理,listOf
,setOf
,mapOf
,创建的都是不可变的集合,需要对应的mutableListOf
,mutableSetOf
,mutableMapOf
才可创建可以改变值的集合
也可以用listOf
创建的集合后调用toMutableList
,注意返回的是新的可变的集合,旧的集合仍旧是不可变的
fun testArray() {
strs[1] = "B"
//map取值
val value1 = map.get(1)
val value2 = map[2]
//可改值的map赋值
mapChange.put(1, "A")
mapChange[1] = "A"
//不可变list改为可变list,注意返回的是可变的,但strList还是不可变的
val staListChange = strList.toMutableList()
}
Sequence
和Iterable
一样,用来遍历一组数据并可以对每个元素进行特定的处理
三种创建方式:
//sequence
var sequence: Sequence<String> = sequenceOf("a", "b", "c")//用一组元素创建
var sequence2: Sequence<String> = strList.asSequence()//使用已创建的list列表转换
var sequence3: Sequence<Int> = generateSequence(0) { it + 1 }//使用lambda表达式创建,0是第一个元素,it表示前一个元素
kotlin
有四种修饰符public
,private
,protected
,internal
1.public
:java
中要显示声明,kotlin
里默认都是public
的
2.internal
:暂时不是很明白,原文记录下
internal 表示修饰的类、函数仅对 module 内可见,这里的 module 具体指的是一组共同编译的 kotlin 文件,常见的形式有:
1.Android Studio 里的 module
2.Maven project
我们常见的是 Android Studio 中的 module 这种情况,Maven project 仅作了解就好,不用细究。
internal 在写一个 library module 时非常有用,当需要创建一个函数仅开放给 module 内部使用,不想对 library 的使用者可见,这时就应该用 internal 可见性修饰符。
3.protected
:java
中表示包内可见 + 子类可见,kotlin
表示private
+ 子类可见
4.private
:java
中表示类中可见,作为内部类时对外部类「可见」,即外部类可以访问内部类的 private 变量,而kotlin
中表示类中或所在文件内可见,作为内部类时对外部类「不可见」
class B {
private val age = 10 //整个文件可见
class C {
private val name = "jack" //仅 C 类中可见
fun testC() {
val b: B = B()
b.age//内部类可以访问外部的private属性
}
}
fun testB() {
val c: C = C()
c.name //报错,提示name属性是private,外部类无法访问内部类变量
}
}
java
中private
不能用来修饰class
和interface
,因为修饰后就无法被使用,而kotlin
中可以用private
修饰class
和interface
,因为kotlin
存在顶层声明,所以可以使用,比如之前的工具类,可以修改为
package com.kotlinpractice.kotlin
val GLOBAL_AGE: Int = 10
fun globalGetScreenHeight(): Int {
return 0
}
private class Util {
//类内部,使用private修饰
}