从0开始复习遍kotlin(1)


准备工作

1.下载android studio 随意创建一个项目.
2.创建一个module.在这里插入图片描述
3.创建一个kotlin文件并手写main方法.
在这里插入图片描述
4.点击运行.
在这里插入图片描述

变量

 //val 只可赋值一次
    val a:Int = 1 //立即赋值
    val b = 1 //'int'类型推断
    val c :Int // 不提供初始值
    c = 1 //延迟赋值
    //var 只重新赋值
    var d = 1
    //a = 2(报错)
    d = 2 

基本类型

//数字
val oneByte:Byte = 1 //Byte 8位
val oneShort:Short = 1 //Short 16位
val one:Int = 1 //Int 32位
val oneLong:Long = 1L//Long 64位
// 浮点
val oneFloat:Float = 1.0F //Float 大小32位 有效位 24
val oneDouble:Double = 1.0 //Double 大小64位 有效位 53

kotlin在jvm上对Integer的内存优化在-128-127之间.

val a:Int = 130
val boxedA:Int? = a
val anotherBoxedA:Int? = a
println(boxedA == anotherBoxedA)//true
println(boxedA === anotherBoxedA)//false

运算符 + - * / %
浮点数比较

  • 平等检查:a==b a != b
  • 比较运算符: a < b ,a > b ,a <= b, a >= b
  • 范围实例化和范围检查 :a…b , x in a…b, x !in a…b
//布尔值
 var myTrue:Boolean = true
 var myfalse:Boolean = false
 println(myTrue || myfalse)//true
 println(myTrue && myfalse)//false
 println(!myTrue)//false
//字符Char
val aChar:Char = 'a'
//字符串String
val str = "abf 123"
//数组
val x: IntArray = intArrayOf(1, 2, 3)
//输出 1 2 3
val arr = IntArray(5)
//输出 0 0 0 0 0
val arr = IntArray(5) { 1 }
//输出 1 1 1 1 1
var arr = IntArray(5) { it * 1 }
//输出 0 1 2 3 4

类型检查 is !is
强制转换 as

函数

fun firstFun(){
    println("第一个fun")
}
//带返回值
fun firstFun():Int{
   return 1
}
//输出1

fun sum() = "函数表达式"

//定义一个类
class first
//加构造参数
class first(var a:Int,var b:Int){
    fun sum() = a + b
}
//两个构造参数
class first(var a:Int,var b:Int){
    constructor( a:Int, b:Int, c:Int):this(a,b){

    }
}
class first(var a:Int,var b:Int){
    fun sum() = a + b
}
//构造参数添加默认值
class first(var a:Int = 1,var b:Int = 2){
    fun sum() = a + b
}
//初始化顺序
class InitOrderDemo(name: String) {
    val firstProperty = "1: $name".also(::println)
    
    init {
        println("2: $name")
    }
    
    val secondProperty = "3: ${name.length}".also(::println)
    
    init {
        println("4: ${name.length}")
    }
}
//init执行在constructor前
class Constructors {
     constructor(i: Int) {
        println("2 Constructor $i")
    }
    init {
        println("1")
    }
}

继承

//继承.要使类可继承,需要用open修饰.
open class first
class two(var a:Int,var b:Int):first()
//执行顺序
open class Base(val name: String) {

    init { println("2 Initializing a base class") }

    open val size: Int = 
        name.length.also { println("3 Initializing size in the base class: $it") }
}

class Derived(
    name: String,
    val lastName: String,
) : Base(name.replaceFirstChar { it.uppercase() }.also { println("1 Argument for the base class: $it") }) {

    init { println("4 Initializing a derived class") }

    override val size: Int =
        (super.size + lastName.length).also { println("5 Initializing size in the derived class: $it") }
}
// 内部类
//在内部类中,使用super外部类名限定的关键字来访问外部类的超类super@Outer
open class Rectangle {
    open fun draw() { println("Drawing a rectangle") }
    val borderColor: String get() = "black"
}

class FilledRectangle: Rectangle() {
    override fun draw() {
        val filler = Filler()
        filler.drawAndFill()
    }

    inner class Filler {
        fun fill() { println("Filling") }
        fun drawAndFill() {
            super@FilledRectangle.draw() // 调用Rectangle 的 draw()
            fill()
            println("color ${super@FilledRectangle.borderColor}") // 调用Rectangle 的 borderColor 的 get() 
        }
    }
}
fun main() {
    val fr = FilledRectangle()
        fr.draw()
}
//输出
//Drawing a rectangle
//Filling
//color black

Overriding rules

当父类与实现接口方法名耦合时。分别调用父类和接口的方法。

open class Rectangle {
    open fun draw() { }
}

interface Polygon {
    fun draw() { } // interface members are 'open' by default
}

class Square() : Rectangle(), Polygon {
    override fun draw() {
        super<Rectangle>.draw() // 调用 Rectangle.draw()
        super<Polygon>.draw() // 调用 Polygon.draw()
    }
}

接口 interface

//使用关键字定义接口interface:
interface MyInterface {
    fun bar()
    fun foo() {
     
    }
}

一个类或对象可以实现一个或多个接口

class Child : MyInterface {
    override fun bar() {
        // body
    }
}

接口属性
interface 属性实现get方法后,实现接口的类颗不用重写此属性。

interface MyInterface {
    val prop: Int // abstract

    val propertyWithImplementation: String
        get() = "foo"

    fun foo() {
        print(prop)
    }
}

class Child : MyInterface {
    override val prop: Int = 29
}

接口继承

interface Named {
    val name: String
}

interface Person : Named {
    val firstName: String
    val lastName: String

    override val name: String get() = "$firstName $lastName"
}

data class Employee(
    // 不用实现name
    override val firstName: String,
    override val lastName: String,
    val position: Position
) : Person

函数(SAM)接口
只有一个抽象方法的接口称为功能接口或单一抽象方法 (SAM) 接口。功能接口可以有多个非抽象成员,但只有一个抽象成员。

fun interface KRunnable {
   fun invoke()
}
val isEven = IntPredicate { it % 2 == 0 }
fun main() {
   println("Is 7 even? - ${isEven.accept(7)}")
}

函数类型的类型别名

typealias IntPredicate = (i: Int) -> Boolean

val isEven: IntPredicate = { it % 2 == 0 }

fun main() {
   println("Is 7 even? - ${isEven(7)}")
}

功能接口和类型别名有不同的用途。类型别名只是现有类型的名称——它们不会创建新类型,而函数式接口会。您可以提供特定于特定功能接口的扩展,使其不适用于普通函数或其类型别名。

类型别名只能有一个成员,而功能接口可以有多个非抽象成员和一个抽象成员。功能接口也可以实现和扩展其他接口。

可见性修饰符

Kotlin 中有四个可见性修饰符:private、protected、internal和public. 默认可见性是public。

  • 如果您不使用可见性修饰符,public则默认使用,这意味着您的声明将在任何地方可见。
  • 如果将声明标记为private,它将仅在包含该声明的文件中可见。
  • 如果将其标记为internal,它将在同一模块中的任何地方可见。
open class Outer {
    private val a = 1
    protected open val b = 2
    internal open val c = 3
    val d = 4  
    protected class Nested {
        public val e: Int = 5
    }
}
class Subclass : Outer() {
    override val b = 5   // 'b' is protected
    override val c = 7   // 'c' is internal
}
class Unrelated(var o: Outer) {
    fun avv(){ 
      o.c // 'c' is internal
    }
}

Modules
internal可见性修饰符意味着该成员在同一模块中是可见的。更具体地说,模块是一组编译在一起的 Kotlin 文件,例如

  • 一个 IntelliJ IDEA 模块。
  • 一个 Maven 项目。
  • Gradle 源集(test源集可以访问 的内部声明main除外)。
  • 使用Ant 任务的一次调用编译的一组文件。

函数扩展

//在不使用继承的情况下给Fdd添加一个add方法
class Fdd{

}
fun Fdd.add(){
    
}

可以在另一个类中声明一个类的扩展。

class Host(val hostname: String) {
    fun printHostname() { print(hostname) }
}

class Connection(val host: Host, val port: Int) {
    fun printPort() { print(port) }

    fun Host.printConnectionString() {
        printHostname()   // calls Host.printHostname()
        print(":")
        printPort()   // calls Connection.printPort()
    }

    fun connect() {
        /*...*/
        host.printConnectionString()   // calls the extension function
    }
}

如果调度接收器和扩展接收器的成员之间发生名称冲突,则扩展接收器优先。要引用调度接收者的成员,您可以使用限定this语法。

属性扩展

val Fdd.a :Int
    get() = 1

伴生对象扩展

class MyClass {
    companion object { }  // will be called "Companion"
}

fun MyClass.Companion.printCompanion() { println("companion") }

数据类

data class User(val name: String, val age: Int)

编译器自动从主构造函数中声明的所有属性派生以下成员:

  • equals()/hashCode()
  • toString()输出"User(name=John, age=42)"
  • componentN()与声明顺序中的属性相对应的函数。
  • copy()

数据类和解构声明

val jane = User("Jane")
val (name) = jane

密封类

以sealed修饰的类或者接口

sealed interface Error

sealed class IOError(): Error //仅在相同的包和模块中扩展
open class CustomError(): Error //可以扩展到任何地方

嵌套类和内部类

class Outer {
    private val bar: Int = 1
    class Nested {
        fun foo() = 2
    }
}

val demo = Outer.Nested().foo() // == 2

内部类
标记为的嵌套类inner可以访问其外部类的成员。内部类携带对外部类对象的引用:

class Outer {
    private val bar: Int = 1
    inner class Inner {
        fun foo() = bar
    }
}

val demo = Outer().Inner().foo() // == 1

枚举类

enum class Direction {
    NORTH, SOUTH, WEST, EAST
}

由于每个枚举都是枚举类的一个实例,因此可以将其初始化为:

enum class Color(val rgb: Int) {
    RED(0xFF0000),
    GREEN(0x00FF00),
    BLUE(0x0000FF)
}

内联类

有时,业务逻辑需要围绕某种类型创建包装器。但是,由于额外的堆分配,它会引入运行时开销。此外,如果包装类型是原始类型,则性能损失很糟糕,因为原始类型通常由运行时进行大量优化,而它们的包装器没有得到任何特殊处理。

为了解决这些问题,Kotlin 引入了一种特殊的类,称为内联类。内联类是基于值的类的子集。他们没有身份,只能持有价值观。

要声明内联类,请value在类名前使用修饰符:

value class Password(private val s: String)

// For JVM backends
@JvmInline
value class Password(private val s: String)
@JvmInline
value class UInt(val x: Int)

// 在jvm上表示 'public final void compute(int x)' 
fun compute(x: Int) { }

// 在jvm上表示 'public final void compute(int x)'
fun compute(x: UInt) { }

条件表达式

fun maxOf(a: Int,b:Int):Int{
    if (a > b){
        return a
    }else{
        return  b
    }
}
//或者
fun maxOf(a: Int,b:Int) = if (a > b) a else b
//when表达式
fun describe(obj:Any):String=
  when(obj){
      1        -> "one"
      "hellow" -> "Greeting"
      is Long  -> "是 Long"
      !is String  ->"不是String"
      else     -> ""
  }
val items = listOf<Int>(1,2,3,4,5)
 when{
      1 in items -> println("items中有1")
      6 in items -> println("items中有6")
  }
 //输出items中有1   

对象表达式

val helloWorld = object {
    val hello = "Hello"
    val world = "World"
   
    override fun toString() = "$hello $world"
}

从object 继承匿名对象

window.addMouseListener(object : MouseAdapter() {
    override fun mouseClicked(e: MouseEvent) { /*...*/ }

    override fun mouseEntered(e: MouseEvent) { /*...*/ }
})

如果超类型具有构造函数,则将适当的构造函数参数传递给它。多个超类型可以指定为冒号后的逗号分隔列表:

open class A(x: Int) {
    public open val y: Int = x
}

interface B { /*...*/ }

val ab: A = object : A(1), B {
    override val y = 15
}

伴随对象

类中的对象声明可以用companion关键字标记:

class MyClass {
    companion object Factory {
        fun create(): MyClass = MyClass()
    }
}

可以通过使用类名作为限定符简单地调用伴生对象的成员:

val instance = MyClass.create()

伴生对象的名称可以省略,在这种情况下Companion将使用名称:

class MyClass {
    companion object { }
}

val x = MyClass.Companion

类成员可以访问相应伴随对象的私有成员。

委托模式

interface Base {
    fun print()
}

class BaseImpl(val x: Int) : Base {
    override fun print() { print(x) }
}

class Derived(b: Base) : Base by b

fun main() {
    val b = BaseImpl(10)
    Derived(b).print()
}

委托属性

  • Lazy properties:该值仅在首次访问时计算。
  • Observable properties:通知侦听器有关此属性的更改。
  • 将属性存储在Map中,而不是每个属性的单独字段。
class Example {
    var p: String by Delegate()
}

属性委托不必实现接口,但必须提供getValue()函数(和setValue()for vars)。

class Delegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "$thisRef, thank you for delegating '${property.name}' to me!"
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("$value has been assigned to '${property.name}' in $thisRef.")
    }
}

当您读取p委托给 的实例的from 时Delegate,将调用getValue()函数 from Delegate。它的第一个参数是您从中读取的对象p,第二个参数包含对p自身的描述(例如,您可以取其名称)。

val e = Example()
println(e.p)

打印结果:Example@33a17727, thank you for delegating ‘p’ to me!

e.p = "NEW"

当您分配给 时p,将调用该setValue()函数。前两个参数是相同的,第三个保存被赋值的值:

打印结果 :NEW has been assigned to 'p' in Example@33a17727.

lazy

lazy()是一个接受 lambda 并返回 的实例的函数,该实例Lazy可以作为实现惰性属性的委托。第一次调用get()执行传递给的 lambdalazy()并记住结果。后续调用get()简单地返回记住的结果。

val lazyValue: String by lazy {
    println("computed!")
    "Hello"
}

fun main() {
    println(lazyValue)
    println(lazyValue)
}

输出:computed!
Hello
Hello

可观察的属性

Delegates.observable()接受两个参数:初始值和修改处理程序。

每次分配给属性时都会调用处理程序(在执行分配之后)。它具有三个参数:分配给的属性、旧值和新值

class User {
    var name: String by Delegates.observable("<no name>") {
        prop, old, new ->
        println("$old -> $new")
    }
}

fun main() {
    val user = User()
    user.name = "first"
    user.name = "second"
}

输出

<no name> -> first
first -> second

委托属性

在不删除或者更改老属性的情况下,创建一个新属性,新属性值更改,老属性随着更改。老属性更改,新属性不变。

class MyClass {
   var newName: Int = 0
   @Deprecated("Use 'newName' instead", ReplaceWith("newName"))
   var oldName: Int by this::newName
}
fun main() {
   val myClass = MyClass()
   myClass.oldName = 42
   println(myClass.newName) // 42
}

在map中存储属性

class User(val map: Map<String, Any?>) {
    val name: String by map
    val age: Int     by map
}
val user = User(mapOf(
    "name" to "John Doe",
    "age"  to 25
))
println(user.name) //  "John Doe"
println(user.age)  //  25

对于只读属性 ( val),委托应提供具有getValue()以下参数的运算符函数:

  • thisRef必须与属性所有者的类型相同或超类型(对于扩展属性,它应该是被扩展的类型)。
  • property必须是类型KProperty<*>或其超类型。
    getValue()必须返回与属性(或其子类型)相同的类型。
class Resource

class Owner {
    val valResource: Resource by ResourceDelegate()
}

class ResourceDelegate {
    operator fun getValue(thisRef: Owner, property: KProperty<*>): Resource {
        return Resource()
    }
}

对于可变属性 ( var),委托必须另外提供具有setValue()以下参数的运算符函数:

  • thisRef必须与属性所有者的类型相同或超类型(对于扩展属性,它应该是被扩展的类型)。
  • property必须是类型KProperty<*>或其超类型。
  • value必须与属性(或其超类型)具有相同的类型。
class Resource

class Owner {
    var varResource: Resource by ResourceDelegate()
}

class ResourceDelegate(private var resource: Resource = Resource()) {
    operator fun getValue(thisRef: Owner, property: KProperty<*>): Resource {
        return resource
    }
    operator fun setValue(thisRef: Owner, property: KProperty<*>, value: Any?) {
        if (value is Resource) {
            resource = value
        }
    }
}

类型别名

类型别名为现有类型提供替代名称。如果类型名称太长,您可以引入不同的较短名称并使用新名称。

缩短长泛型

typealias NodeSet = Set<Network.Node>

typealias FileTable<K> = MutableMap<K, MutableList<File>>

为函数类型提供不同的别名

typealias MyHandler = (Int, String, Any) -> Unit

typealias Predicate<T> = (T) -> Boolean

为内部类和嵌套类指定新名称:

class A {
    inner class Inner
}
class B {
    inner class Inner
}

typealias AInner = A.Inner
typealias BInner = B.Inner
typealias Predicate<T> = (T) -> Boolean

fun foo(p: Predicate<Int>) = p(42)

fun main() {
    val f: (Int) -> Boolean = { it > 0 }
    println(foo(f)) // prints "true"

    val p: Predicate<Int> = { it > 0 }
    println(listOf(1, -2).filter(p)) // prints "[1]"
}

for while 循环

循环遍历

val items = listOf<Int>(1,2,3,4,5)
	for (item in items){
        println(item)
    }
    for (index in items.indices){
        println(items[index])
    }
    items.forEach {
        println(it)
    }
    var index = 0
    while (index < items.size){
        println(items[index])
    }

循环跳出jumps与返回Returns

Kotlin 有三种结构跳转表达式:

  • return默认情况下从最近的封闭函数或匿名函数返回。
  • break终止最近的封闭循环。
  • continue进入最近的封闭循环的下一步。
 first@ for (i in 1..100) {
        if (i == 10) break@first
        for (j in 1..100) {
            print("j=$j")
            if (j == 5) break@first
        }
    }
 // continue使用方式与break一样   
//中断forEach
fun foo() {
    listOf(1, 2, 3, 4, 5).forEach lit@{
        if (it == 3) return@lit 
        print(it)
    }
}
//外部嵌套run函数
run loop@{
        listOf(1, 2, 3, 4, 5).forEach {
            if (it == 3) return@loop 
            print(it)
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值