Java开发学习Kotlin 笔记
Kotlin
三元:
val max = if (a > b) a else b
fun OfferType.Companion.fromString(str: String?): OfferType {
//字符串可能为空
if (str?.isBlank() == true) {
return OfferType.STUDIO_FLOW
}
for (type in OfferType.values())
if (type.str.equals(str, ignoreCase = true))
return type
throw UnprocessableEntity("No Offer Type with '$str' found")
}
输出
println()
//sampleStart
fun sum(a: Int, b: Int) = a + b
//sampleEnd
fun main() {
println("sum of 19 and 23 is ${sum(19, 23)}")
}
返回为空的类型:Unit
定义只读局部变量使用关键字 val 定义。只能为其赋值一次。
可重新赋值的变量使用 var 关键字。
函数的变长参数可以用 vararg 关键字进行标识:
fun vars(vararg v:Int){
for(vt in v){
print(vt)
}
}
$varName 表示变量值
${varName.fun()} 表示变量的方法返回值:
//age为空返回-1
val ages2 = age?.toInt() ?: -1
类型转换:
if (obj is String) {
// 做过类型判断以后,obj会被系统自动转换为String类型
return obj.length
}
在 Kotlin 中,三个等号 === 表示比较对象地址,两个 == 表示比较两个值大小。
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> { // 注意这个块
print("x 不是 1 ,也不是 2")
}
}
主构造器中不能包含任何代码,初始化代码可以放在初始化代码段中,初始化代码段使用 init 关键字作为前缀。
class Person constructor(firstName: String) {
init {
println("FirstName is $firstName")
}
}
次要构造函数: constructor
内部类使用 inner 关键字来表示。
abstract // 抽象类
final // 类不可继承,默认属性
enum // 枚举类
open // 类可继承,类默认是final的
annotation // 注解类
Kotlin 中所有类都继承该 Any 类,它是所有类的超类
接口中的属性
接口中的属性只能是抽象的,不允许初始化值,接口不会保存属性值,实现接口时,必须重写属性:
interface MyInterface{
var name:String //name 属性, 抽象的
}
class MyImpl:MyInterface{
override var name: String = "runoob" //重写属性
}
扩展函数可以在已有类中添加新的方法,不会对原类做修改,扩展函数定义形式:
fun receiverType.functionName(params){
body
}
- receiverType:表示函数的接收者,也就是函数扩展的对象
- functionName:扩展函数的名称
- params:扩展函数的参数,可以为NULL
标准库提供了 Pair 和 Triple
Kotlin 使用 object 关键字来声明一个对象。
Kotlin 中我们可以方便的通过对象声明来获得一个单例。 里面的方法都是public static的
类内部的对象声明可以用 companion 关键字标记,这样它就与外部类关联在一起,我们就可以直接通过外部类访问到对象的内部元素。class MyClass {
companion object Factory {
fun create(): MyClass = MyClass()
}
}
val instance = MyClass.create() // 访问到对象的内部元素
声明可空变量
var/val 变量名 : 类型? = null/确定的值
后期初始化
// 声明组件
private lateinit var mTabLayout : TabLayout
常量
const val NUM_A = 6
val arrTest : Array<Int?> = arrayOf(1,2,null,3,null,5,6,null)
// 传统写法
for (index in arrTest) {
if (index == null){
continue
}
println("index => $index")
}
// let写法
for (index in arrTest) {
index?.let { println("index => $it") }
}
- let操作符的作用:当时用符号?.验证的时候忽略掉null
- let的用法:变量?.let{ ... }
索引遍历:
val items = listOf("apple", "banana", "kiwifruit")
for (index in items.indices) {
println("item at $index is ${items[index]}")
}
函数的入参的默认参数
numC : Boolean = false
- public修饰符表示 公有 。此修饰符的范围最大。当不声明任何修饰符时,系统会默认使用此修饰符。
- internal修饰符表示 模块 。对于模块的范围在下面会说明。
- protected修饰符表示 私有+子类。值得注意的是,此修饰符不能用于顶层声明,在下面可以看到。
- private修饰符表示 私有 。此修饰符的范围最小,即可见性范围最低。
Kotlin的默认修饰符为public,Java的默认修饰符为default
Kotlin的超类是:Any
- 定义继承类的关键字为:open。不管是类、还是成员都需要使用open关键字。
当一个类不是用open修饰符修饰时,这个类默认是final的。即:
class A{} 等价于 final class A{} // 注意,则的`final`修饰符在编辑器中是灰色的,因为Kotlin中默认的类默认是final的
数据类
data class User(val name : String, val pwd : String)
修改属性值.
val mUser = User("kotlin","123456")
val mNewUser = mUser.copy(name = "new Kotlin")
//Koltin要修改数据类的属性,则使用其独有的copy()函数。其作用就是:修改部分属性,但是保持其他不变
密封类
不能被实例化
sealed class SealedExpr{
data class Person(val num1 : Int, val num2 : Int) : SealedExpr()
object Add : SealedExpr() // 单例模式
object Minus : SealedExpr() // 单例模式
}
// 其子类可以定在密封类外部,但是必须在同一文件中 v1.1之前只能定义在密封类内部
object NotANumber : SealedExpr()
密封类的子类必须是在密封类的内部或必须存在于密封类的同一文件。这一点就是上面提到的有效的代码保护。
因为kotlin没有static,所以使用伴生对象
- 每个类最多定义一个伴生对象;
- 伴生对象相当于外部类的对象,可以直接通过外部类名访问伴生对象的成员;
- 由于kotlin取消了static关键字,伴生对象是为了弥补kotlin没有static关键字修饰的静态成员的不足;
- 虽然伴生对象是为其所在对象模拟静态成员,但是伴生对象成员依然属于伴生对象本身的成员,而不属于其外部类的成员。
fun main() {
println(OuterClass.name)//伴生对象属性
OuterClass.companionFun()//调用伴生对象方法
println(OuterClass.extraParam)//为伴生对象扩展属性
OuterClass.test()//为伴生对象扩展方法
}
class OuterClass {
companion object {
val name = "伴生对象属性"
fun companionFun() {
println("调用伴生对象方法")
}
}
}
/**
* 为伴生对象扩展方法
*/
fun OuterClass.Companion.test() {
println("为伴生对象扩展方法")
}
/**
* 为伴生对象扩展属性
*/
val OuterClass.Companion.extraParam: String
get() = "为伴生对象扩展属性"
有名字的伴生对象:
fun main() {
println(OuterClass.name)//伴生对象属性
OuterClass.companionFun()//调用伴生对象方法
OuterClass.CompanionObjectName//通过伴生对象名称获取伴生对象本身
}
class OuterClass {
companion object CompanionObjectName {
val name = "伴生对象属性"
fun companionFun() {
println("调用伴生对象方法")
}
}
}
遍历 map/pair型list
for ((k, v) in map) {
println("$k -> $v")
}
k、v 可以改成任意名字。
使用区间:
for (i in 1..100) { …… } // 闭区间:包含 100
for (i in 1 until 100) { …… } // 半开区间:不包含 100
for (x in 2..10 step 2) { …… }
for (x in 10 downTo 1) { …… }
if (x in 1..10) { …… }
If not null 缩写
val files = File("Test").listFiles()
println(files?.size)
If not null and else 缩写
val files = File("Test").listFiles()
println(files?.size ?: "empty")
if null 执行一个语句
val values = ……
val email = values["email"] ?: throw IllegalStateException("Email is missing!")
在可能会空的集合中取第一元素
val emails = …… // 可能会是空集合
val mainEmail = emails.firstOrNull() ?: ""
if not null 执行代码
val value = ……
value?.let {
…… // 代码会执行到此处, 假如data不为null
}
映射可空值(如果非空的话)
val value = ……
val mapped = value?.let { transformValue(it) } ?: defaultValue
// 如果该值或其转换结果为空,那么返回 defaultValue。
try-catch 表达式:
fun test() {
val result = try {
count()
} catch (e: ArithmeticException) {
throw IllegalStateException(e)
}
// 使用 result
}
TODO():将代码标记为不完整
Kotlin 的标准库有一个 TODO() 函数,该函数总是抛出一个 NotImplementedError。 其返回类型为 Nothing,因此无论预期类型是什么都可以使用它。 还有一个接受原因参数的重载:
fun calcTaxes(): BigDecimal = TODO("Waiting for feedback from accounting")
IntelliJ IDEA 的 kotlin 插件理解 TODO() 的语言,并且会自动在 TODO 工具窗口中添加代码指示。