Kotlin 基础学习
NULL检查机制
Kotlin的空安全设计对于声明可为空的参数,在使用是进行空判断处理,有两种处理方式,字段后加 !! 像 java 一样抛出空异常,另外字段后面加 ? 可不做处理返回值为 null 或者配合 ?: 做空判断处理。
//类型后面加 ? 表示可为空val age: String? = null//抛出空指针异常val ages = age!!.toInt()//不做处理返回 nullval ages1 = age?.toInt()//age 为空返回 -1val ages2 = age?.toInt() ?: -1
类型检测及自动类型转换
我们可以使用 is 运算符检测一个表达式是否某类型的一个实例(类似于 java 中的 instanceof关键字)
fun getStringLength(obj: Any): Int? {if (obj !is String) return null//在这个分支中,‘obj’ 的类型会被自动转换为 ‘String’return obj.length
}
区间
区间表达式由具有操作符形式 .. 的rangeTo 函数辅以 in 和 !in 形成。
for (i in 1..4) print(i) //输出 1234for (i in 4..1) print(i) // 什么都不输出//使用 step 指定步长for (i in 1..4 step 2) print(i) //设置跳过 2 步 执行:输出 13for (i in 4 downTo 1 step 2) print(i)//输出 42//使用 until 函数排除结束元素for (i in 1 until 10) print(i) // i in [1,10) 排除了 10 :输出: 123456789
字面常量
val int = 123 // 十进制val int1 = 123L //长整型以大写的 L 结尾val data = 0x0f //16进制以 0x 开头: 0x0Fval data2 = 0b00001011 //2 进制以 0b 开头//Doubles 默认写法 123.5 123.5e10val double = 123.5val double2 = 123.5e10val floats = 123.5f//可以使用下划线使数字常量更易读val oneMillion: Int = 1_000_100
比较两个数字
Kotlin 中没有基础数据类型,只有封装的数字类型,你每定义的一个变量,其实 Kotlin 帮你封装了一个对象,这样可以保证不会出现空指针。数字类型也一样,所以在比较两个数字的时候,就有比较数据大小和比较两个对象是否相同的区别。
在 Kotlin 中,三个等号 === 表示比较对象地址,两个 == 表示比较两个值大小。
fun test4() {val a = 1000println(a === a) //值相等,对象地址相等 输出:true//经过了装箱,创建了两个不同的对象val boxedA: Int? = aval anotherBoxedA: Int? = a//虽然经过了装箱,但是值是相等的println(boxedA === anotherBoxedA) //值相等,对象地址不一样 输出:falseprintln(boxedA == anotherBoxedA) //值相等 输出:true
}
类型转换
由于不同的表示方式,较小类型并不是较大类型的子类型,较小的类型不能隐式转换较大的类型,这意味着在不进行显式转换的情况下沃恩不能把 Byte 型值赋给一个 Int 变量
fun test5(){val b: Byte = 1// OK 字面值是静态检测的val i:Int = b//错误
}
位操作符
对于 Int 和 Long 类型,还有一系列的位操作符可以使用
字符 Char
fun decimalDigitValue(c: Char): Int {if (c !in '0'..'9')throw IllegalArgumentException("Out of range")return c.toInt() - '0'.toInt() // 显式转换为数字
}
数组
数组用类 Array 实现,并且还有一个 size 属性及 get 和 set 方法,由于使用 [] 重载了 get 和 set 方法,所以我们可以通过下标很方便的获取或者设置数组对应位置的值。
数组的创建两种方式:一种是使用函数 arrayOf(); 另外一种是使用工厂函数,如下所示,我们分别是两种方式创建了两个数组:
fun test6() {val a = arrayOf(1, 2, 3) //输出:[1,2,3]for (i in a) print(i)print("-------------------------")val b = Array(3) { i -> (i * 2) }//输出: [0,2,4]for (i in b) print(i)
}
字符串
Kotlin支持三个引号 “”” 扩起来的字符串,支持多行字符串.String 可以通过 trimMargin() 方法来删除多余的空白。
fun test7() {val text = """多行字符串多行字符串"""println(text)//输出有一些前置空格
}
fun test7() {val text = """|多行字符串|多行字符串""".trimMargin()print(text)//输出有一些前置空格//print(text.trimMargin())
}
字符串模版
字符串可以包含模版表达式,即一些小段代码,会求值并把结果合并到字符串中,模版表达式以美元符 $ 开头,由一个简单的名字构成
fun test8() {val i = 10val s = "i = $i"print(s)
}
或者用花括号括起来的任意表达式
fun test8() {val i = 10val s = "i = $i"println(s)val s2 = "runoob"val str = "$s2.length is ${s2.length}"println(str)
}
IF表达式
fun test9() {val a = 1val b = 2val max = if (a > b) a else bprintln(max)
}
使用区间
fun test10() {val x = 1 //输出:x 在区间内if (x in 1..9) {println("x 在区间内")}
}
When 表达式
when 将它的参数和所有的分支条件顺序比较,直到某个分支满足条件。
when 既可以被当做表达式使用也可以被当做语句使用。如果它被当做表达式,符合条件的分支的值就是整个表达式的值,如果当做语句使用,则忽略个别分支的值。
when 类似其他语言的 switch 操作符,其最简单的形式如下:
fun test11(){val x = 1 //输出:x == 1when(x){1 -> print("x == 1")else ->{print("x 不是 1,也不是 2")}}
}
when 中使用 in 运算符来判断集合内是否包含某实例:
fun test12() {val items = setOf("apple", "banana", "kiwi")when {"orange" in items -> println("juicy")"apple" in items -> println("apple is fine too")}//输出:apple is fine too
}
For 循环
for 循环可以对任何提供迭代器 iterator 的对象进行遍历,语法如下:
for (item in collection) print( item )
fun test13() {val items = listOf("apple", "banana", "kiwi")for (item in items) println(item)println("--------------------------")for (index in items.indices)println("item at $index is ${items[index]}")println("--------------------------")for ((index, value) in items.withIndex())println("item at $index is $value")
}
while 与 do...while 循环
while 是最基本的循环,它的结构为:
while(布尔表达式) {
//循环内容
}
返回和跳转
Kotlin 有三种结构化跳转表达式:
return 默认从最直接包围它的函数或者匿名函数返回
break 终止最直接包围它的循环
continue 继续下一次最直接包围它的循环
fun test14() {for (i in 1..10) {if (i == 3) continue// i 为 3 时跳出当前循环,继续下一次循环print(i)if (i > 5) break}//输出:12456
}
Kotlin 类和对象
类定义
Kotlin 类可以包含:构造函数和初始化代码块、函数、属性、内部类、对象声明
Kotlin 中使用关键字 class 声明类,声明紧跟类名:
class Runoob{
//大括号内是类的体构成
}
类属性
class Runoob{
var name:String = "Runoob"
}
//Kotlin 中的类可以有一个 主构造器,以及一个或多个次构造器,主构造器是类头部的一部分,位于类名称之后
class Person constructor(firstName: String) {}//如果主构造器没有任何注解,也没有任何可见度修饰符,那么 constructor关键字可以省略
class Person2(firstName: String) {}
getter 和 setter
fun test15() {var person = Person3()println("person.lastName:${person.lastName}")person.no = 99println("no:${person.no}")//输出:// person.lastName:LONG//no:-1
}class Person3 {var lastName = "long"get() = field.toUpperCase()var no = 100set(value) {field = if (value < 10) {value} else {-1}}
}
lateinit
非空属性必须在定义的时候初始化,kotlin提供了一种可以延迟初始化的方案使用 lateinit 关键字描述属性;
主构造器
主构造器中不能包含任何代码,初始化代码可以放在初始哈代码段中,初始化代码段使用 init 关键字作为前缀。
//Kotlin 中的类可以有一个 主构造器,以及一个或多个次构造器,主构造器是类头部的一部分,位于类名称之后
class Person constructor(firstName: String) {init {println("firstName is $firstName")}
}
次构造函数
如果类有主构造函数,每个次构造函数都要,或直接或间接通过另外一个次构造函数代理主构造函数。在同一个类中代理另外一个次构造函数使用 this 关键字:
class Person4(val name: String) {constructor(name: String, age: Int) : this(name) {}
}
//私有构造函数
class Customer private constructor(){}
抽象
抽象是面向对象编程的特征之一,类本身,或类中的部分成员,都可以声明为 abstract 的。抽象成员在类中不存在具体的视线。
注意:无需对抽象类或抽象成员标注 open 注解。
open class Base{open fun f(){}
}abstract class Derived:Base(){override fun f() { }
}
嵌套类
class Outer {private val bar = 1class Nested {fun foo() = 2}
}fun test17() {val demo = Outer.Nested().foo() //调用格式: 外部类.嵌套类().嵌套类方法/属性println(demo)//输出: 2
}
内部类
内部类使用 inner 关键字来表示
内部类会带有一个对外部类的对象引用,所以内部类可以访问外部类成员属性和成员函数。
class Outer2 {private val bar = 1var v = "成员属性"/*嵌套内部类*/inner class Inner {fun foo() = bar//访问外部类成员fun innerTest() {var o = this@Outer2println("内部类可以引用外部类的成员 例如:${o.v}")}}
}fun test18() {val demo = Outer2().Inner().foo()println(demo)val demo2 = Outer2().Inner().innerTest()println(demo2) // 内部类可以引用外部类的成员,例如:成员属性
}
为了消除歧义,要访问来自外部作用域的 this ,我们使用 this@label, 使用 @label 是一个代指 this 来源的标签。
匿名内部类
使用对象表达式来创建匿名内部类
class Test {var v = "成员属性"fun setInterFace(test: TestInterFace) {test.test()}
}/*** 定义接口*/
interface TestInterFace {fun test()
}fun test19() {var test = Test()/*** 采用对象表达式来创建接口对象,即匿名内部类的实例*/test.setInterFace(object : TestInterFace {override fun test() {println("对象表达式创建匿名内部类的实例")}})
}
类的修饰符
类的修饰符包括 classModifier 和 acessModifier
classModifier 类属性修饰符,表示类本身特性abstract //抽象类 final //类不可集成,默认属性 enum //枚举类 open //类可继承,类默认是 final anotation //注解类accessModifier 访问权限修饰符private //仅在同一个文件中可见 protected //同一个文件夹中或子类可见 public // 所有调用的地方可见 internal // 同一个模块中可见
Kotlin 继承
Kotlin 中所有类都继承该 Any类,它是所有类的超类,对于没有超类型声明的类是默认超类:
class Example //从 Any 隐式继承
构造函数
子类有主构造函数
如果子类有主构造函数,则基类必须在主构造函数中立即初始化
class Student(firstName: String) :Example(firstName){}open class Example constructor(firstName: String){}
子类没有主构造函数
如果子类没有主构造函数,则必须在每个二级构造函数中用 super 关键字初始化基类,或者在代理另一个构造函数。初始化基类时,可以调用基类的不同构造方法。
open class Student(firstName: String) : Example(firstName) {}open class Example constructor(firstName: String) {}class Student2 : Student {constructor(firstName: String) : super(firstName) {}
}
重写
在基类中,使用 fun 声明函数时,此函数默认为 final 修饰,不能被子类重写。如果允许子类重写该函数,那么就要手动添加 open 修饰它。子类重新方法使用 override 关键词:
/*** 用户基类*/
open class Person5 {open fun study() {println("我毕业了")}
}/*** 子类继承*/
class Student3 : Person5() {override fun study() {//重写方法super.study()println("我在读大学")}
}fun test20() {val s = Student3()s.study()
}
如果有多个相同的方法(继承或者实现自其他类,如A类,B类),则必须要重写该方法,使用 super 泛型去选择性地调用父类的实现。
interface B {fun f() {println("B")}
}class C : A(), B {override fun f() {super<A>.f()//调用 A.f()super<B>.f()//调用 B.f()}
}fun test21() {val c = C()c.f()//输出 A B
}
属性重写
属性重写使用 override 关键字,属性必须具有兼容类型,每一个声明的属性都可以通过初始化程序或者 getter 方法被重写
open class Foo {open val x = 100
}class Bar1 : Foo() {override val x: Intget() = super.x
}
Kotlin 接口
Kotlin 接口与 java8 类似,使用 interface 关键字定义接口,允许方法有默认实现。
interface MyInterface {fun bar() //未实现fun foo() { //已实现//可选的方法体println("foo")}
}
实现接口
一个类或者对象可以实现一个或者多个接口
interface MyInterface {fun bar() //未实现fun foo() { //已实现//可选的方法体println("foo")}
}class Child : MyInterface {override fun bar() {TODO("Not yet implemented")}
接口中的属性
接口中的属性只能是抽象的,不允许初始值,接口不会保存属性值,实现接口时,必须重写属性:
interface MyInterface2 {var name: String //name 属性,抽象的
}class MyImpl : MyInterface2 {override var name: String = "runoob" //重写属性
}
函数重写
实现多个接口时,可能会遇到同一个方法继承多个实现的问题。
interface D {fun foo() {println("D") //已实现}fun bar() //为实现,没有方法体,是抽象的
}interface E {fun foo() { //已实现println("E")}fun bar() { //已实现println("bar")}
}class F : D {override fun bar() { //重写println("bar")}
}class G : D, E {override fun foo() {super<D>.foo()super<E>.foo()}override fun bar() {super<E>.bar()}
}fun test22() {val g = G()g.foo()g.bar()
//输出:D E bar
}
Kotlin 扩展
Kotlin 可以对一个类的属性和方法进行扩展,且不需要继承或使用 decorator 模式。
扩展是一种静态行为,对被扩展的类代码本身不会造成任何影响。
扩展函数
扩展函数可以在已有类中添加新方法,不会对原类做修改,扩展函数定义形式:
class User(var name: String)fun User.print() {println("用户名 $name")
}fun test23() {val user = User("longsq")user.print()//输出:用户名 longsq
}
扩展函数是静态解析的
扩展函数是静态解析的,并不是接受者类型的虚拟成员,在调用扩展函数时,具体被调用的是那个函数,有调用函数的对象表达式决定的,而不是动态类型决定。
open class H
class I : H()fun H.foo() = "h" //扩展函数 foo
fun I.foo() = "d" //扩展函数 foofun printFoo(h: H) {println(h.foo()) //类型是 H 类
}
若扩展函数和成员函数一致,则使用该函数时,会优先使用成员函数
class AA {fun foo() {println("成员函数")}
}fun AA.foo() {println("扩展函数")
}fun test24() {val aa = AA()aa.foo()//输出成员函数
}
扩展一个空对象
在扩展函数内,可以通过 this 来判断接收者是否为 NULL 这样,即使接收者为 NULL ,也可以调用扩展函数,例如
fun Any?.toString(): String {if (this == null) return "null"// 空检测之后, “this” 会自动转换为非空类型,所以下面的 toString()// 解析为 Any 类的成员函数return toString()
}fun test25() {val t = nullprintln(t.toString())//输出:null
}
伴生对象的扩展
伴生对象类似 java 中静态方法
如果一个类定义有一个伴生对象,你也可以为伴生对象定义扩展函数和属性。
伴生对象通过 类名.形式调用伴生对象,伴生对象声明的扩展函数,通过用类名限定符来调用;
class MyClass {companion object {}//将被成为 companion
}fun MyClass.Companion.foo() {println("伴随对象的扩展函数")
}val MyClass.Companion.no: Intget() = 10fun test26() {println("no:${MyClass.no}")MyClass.foo()/*** 输出:* no:10伴随对象的扩展函数*/
}
扩展的作用域
通常扩展函数或者属性定义在顶级包下
要使用所定义包之外的一个扩展,通过 import 导入扩展的函数名进行使用
扩展声明为成员
在一个类内部你可以为另一个类声明扩展
在这个扩展中,有个多个隐含的接收者,其中扩展方法定义所在类的实例称为分发接受者,而扩展方法的目标类型的实例称为扩展接受者。
class DD {fun bar() {println("DD bar")}
}class CC {fun baz() {println("CC baz")}fun DD.foo() {bar() //调用 DD.barbaz() // 调用 CC.baz}fun caller(d: DD) {d.foo() //调用扩展函数}
}fun test27() {val dd = DD()val cc = CC()cc.caller(dd)/*输出:DD barCC baz*/
}
假如在调用某一个函数,而该函数在分发接受者和扩展接收者均存在,则以扩展接收者优先,要引用分发接收者的成员你可以使用限定的 this 语法。
class DD {fun bar() {println("DD bar")}
}class CC {fun bar() {println("CC bar")}fun baz() {println("CC baz")}fun DD.foo() {this@CC.bar() //调用 DD.barbaz() // 调用 CC.baz}fun caller(d: DD) {d.foo() //调用扩展函数}
}
Kotlin 数据类与密封类
数据类
kotlin 可以创建一个只包含数据的类,关键字 data
data class User2(val name: String, val age: Int)
复制
复制使用 copy() 函数,我们可以使用该函数复制对象并修改部分属性,对上文的User2 类
密封类
sealed class Expr
data class Const(val number: Double) : Expr()
data class Sun(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()fun eval(expr: Expr): Double = when (expr) {is Const -> expr.numberis Sun -> eval(expr.e1) + eval(expr.e2)NotANumber -> Double.NaN//不再需要 else 子句,因为我们已经覆盖了所以的情况
}
Kotlin 泛型
泛型,即 参数类型 ,将类型参数化,可以用在类,接口,方法上。
声明一个泛型类
class Box<T>(t: T) {val value = t
}
创建类的实例时我们需要指定类型参数
class Box<T>(t: T) {val value = t
}fun test28() {val box = Box<Int>(1);val box2 = Box(1)
}
泛型函数
kotlin 泛型函数的声明与 java 相同,类型参数要放在函数名的前面
class Box<T>(t: T) {val value = t
}fun <T> boxInt(value: T) = Box(value)
泛型约束
我们可以使用泛型约束来设定一个给定参数允许使用的类型
kotlin 中使用:对泛型的类型上限进行约束。
fun <T:Comparable<T>> sort(list:List<T>){}
型变
声明处型变
声明处的类型变异使用协变修饰符:in、out、消费者in、生产者out
使用 out 使得一个类型参数协变,协变类型参数只能用作输出,可以作为返回值类型但是无法作为入参的类型:
class Runoob<out A>(val a: A) {fun foo(): A {return a}
}fun test29() {var strCo = Runoob("a")var anyCo = Runoob<Any>("b")anyCo = strCoprintln(anyCo.foo())//输出:a
}
in 使得一个类型参数逆变,逆变类型参数只能用作输入,可以作为入参的类型但是无法作为返回值的类型;
//定义一个支持逆变的类
class Runoob2<in A>(a: A) {fun foo(a: A) {}
}
Kotlin枚举类
枚举类最基本的用法是实现一个类型安全的枚举。
枚举常量用逗号分隔,每个枚举常量都是一个对象。
enum class Color {RED,BLACK,BLUE,GREEN,WHITE
}
枚举初始化
每一个枚举都是枚举类的实例,他们可以被初始化
enum class Color2(val rgb: Int) {RED(0xFF0000),GREEN(0x00ff00),BLUE(0x0000FF)
}
enum class Color {RED,BLACK,BLUE,GREEN,WHITE
}fun test30() {val color = Color.BLUEprintln(Color.values())println(Color.valueOf("RED"))println(color.name)println(color.ordinal)
}
可以使用 enumValues<T>() 和 enumValueOf<T>() 函数以泛型方式访问枚举中的常量。
enum class RGB { RED, GREEN, BLUE }inline fun <reified T : Enum<T>> printAllValue() {print(enumValues<T>().joinToString { it.name })
}fun test31() {printAllValue<RGB>()
}
Kotlin 对象表达式和对象声明
Kotlin 用对象表达式和对象声明来实现创建一个对某个类做了轻微改动的类的对象,且不需要去声明一个新的子类。
fun test32() {val site = object {val name = "菜鸟教程"val url = "www.runoob.com"}println(site.name)println(site.url)
}
class J{//私有函数,所以其返回类型是匿名对象类型private fun foo() = object {val x = "x"}//共有函数,所以其返回类型是 Anyfun publicFoo() = object {val x = "x"}fun bar(){val x1 = foo().x //没有问题//val x2 = publicFoo().x //错误:未能解析的引用 "x"}
}
对象声明
Kotlin 使用 object 关键字来声明一个对象。
kotlin 中我们可以方便的通过对象声明来获得一个单例。
class Site{val name = "菜鸟教程"object DeskTop{val url = "www.runoob.com"fun showName(){//println("desk legs $name") //错误,不能访问到外部类的方法和变量}}
}fun test33(){val site = Site()//site.DeskTop.url //错误,不能通过外部类的实例访问到该对象Site.DeskTop.url //正确
}
伴生对象
类内部的对象声明可以用 companion 关键字标记,这样它就与外部类关联在一起,我们就可以直接通过外部类访问对象的内部元素。
class MyClass2 {companion object Factory {fun create() = MyClass()}
}fun test34() {val instance = MyClass2.create()//访问到对象的内部元素
}
对象表达式和对象声明之间的语义差异
对象表达式是在使用他们的地方立即执行
对象声明是在第一次被访问到时延时初始化
伴生对象的初始化是在相应的类被加载时,与 java 静态初始化器的语义相匹配
Kotlin 委托
委托模式是软件设计模式中的一项基本技巧。在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。
类委托
类的委托即一个类中定义的方法实际是调用另一个类的对象的方法实现的。
//创建接口
interface Base2 {fun print()
}//实现此接口的被委托的类
class Base2Impl(val x: Int) : Base2 {override fun print() {print(x)}
}//通过关键字 by 建立委托类
class Derived2(b: Base2) : Base2 by bfun test35() {val b = Base2Impl(10)Derived2(b).print()//输出:10
}
属性委托
属性委托指的是一个类的某个属性值不是在类中直接进行定义,而是将其托付给一个代理类,从而实现对该类的属性统一管理。
属性委托语法格式:
var/val <属性名>: <类型> by <表达式>
定义一个被委托的类
该类需要包含 getValue() 方法 和 setValue() 方法,且参数 thisRef 为惊醒委托的类对象,prop为进行委托的属性的对象。
//定义包含属性委托的类
class Example2 {var p: String by Delegate()
}//委托的类
class Delegate {operator fun getValue(thisRef: Any?, property: KProperty<*>): String {return "$thisRef, 这里委托了 ${property.name}属性"}operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {println("$thisRef 的 ${property.name} 属性赋值为 $value")}
}fun test36() {val e = Example2()println(e.p) //访问该属性,调用 getValue() 函数e.p = "Runoob" //调用 setValue 函数println(e.p)/*** 输出:* com.gxx.testkotlindemo.Example2@77459877, 这里委托了 p属性com.gxx.testkotlindemo.Example2@77459877 的 p 属性赋值为 Runoobcom.gxx.testkotlindemo.Example2@77459877, 这里委托了 p属性*/
}
标准委托
Kotlin 的标准库中已经内置了很多工厂方法来实现属性的委托
延迟属性 Lazy
lazy() 是一个函数。接受一个 Lambda 表达式作为参数,返回一个Lazy<T> 实例的函数。返回的实例可以作为实现延迟属性的委托:
第一次调用 get() 会执已传递给 lazy() 的lambda 表达式并记录结果,后续调用 get() 只是返回记录的结果。
val lazyValue: String by lazy {println("computed!") //第一次调用输出,第二次调用不执行"Hello"
}fun test37() {println(lazyValue) //第一次执行,执行两次输出表达式println(lazyValue) //第二次执行,只输出返回值/*** 输出:* computed!HelloHello*/
}
可观察属性 Observable
observable 可以用于实现观察者模式。
Delegates.observable() 函数接受两个参数,第一个是初始值,第二个是属性值变化事件的响应器。
class User3 {var name: String by Delegates.observable("初始值") { property, oldValue, newValue ->println("旧值: $oldValue -> 新值:$newValue")}
}fun test38() {val user = User3()user.name = "第一次赋值"user.name = "第二次赋值"/*** 输出:* 旧值: 初始值 -> 新值:第一次赋值旧值: 第一次赋值 -> 新值:第二次赋值*/
}
把属性储存在映射中
class Site2(val map: Map<String, Any?>) {val name: String by mapval url: String by map
}fun test39() {val site = Site2(mapOf("name" to "菜鸟教程","url" to "www.runoob.com"))//读取映射值println(site.name)println(site.url)/*** 输出:* 菜鸟教程www.runoob.com*/
}
相关文章:
Kotlin 基础学习
NULL检查机制 Kotlin的空安全设计对于声明可为空的参数,在使用是进行空判断处理,有两种处理方式,字段后加 !! 像 java 一样抛出空异常,另外字段后面加 ? 可不做处理返回值为 null 或者配合 ?: 做空判断处理。 //类型后面加 ? 表…...
CW6B-90A-RCW6B-100A-RCW6B-110A-RCW6B-115A-R三相三线式滤波器
CW4B-10A-S CW4B-20A-S CW4B-30A-S三相三线式滤波器 CW6B-50A-S CW6B-60A-S CW6B-70A-S CW6B-80A-S CW6B-90A-S CW6B-100A-S CW6B-250A-S三相三线式滤波器 CW12B-3A-S(005) CW12B-6A-S(005) CW12B-10A-S(005) CW12B-20A-S(005 CW12B-30A-S(005) CW12B-40A-S(005)三…...
DP读书:鲲鹏处理器 架构与编程(九)鲲鹏920处理器片上系统
鲲鹏920片上系统 鲲鹏920处理器片上系统的组织与管理鲲鹏920片上系统的配置鲲鹏处理器多芯片系统鲲鹏2P多芯片系统鲲鹏4P多芯片系统鲲鹏920处理器片上系统和I/O桥组成的多芯片系统 鲲鹏920处理器的管理和安全架构鲲鹏920片上系统的PMU 鲲鹏920处理器片上系统的输入与输出鲲鹏92…...
【HBZ分享】java中的BitSet 与 Redis中的BitMap 与 布隆过滤器
BitMap的存储原理 bitMap他会标识出某个整数是否存在,存在即为1,不存在对应位即为0bitMap是存储int类型的,int 4byte, 1byte 8bit,因此bitMap数组中的每个下标可以标识出32个数字是否存在bitMap相当于一个个小格子&…...
《Linux从练气到飞升》No.16 Linux 进程地址空间
🕺作者: 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux菜鸟刷题集 😘欢迎关注:👍点赞🙌收藏✍️留言 🏇码字不易,你的👍点赞🙌收藏❤️关注对我真的…...
【算法题】7004. 判别首字母缩略词
题目: 给你一个字符串数组 words 和一个字符串 s ,请你判断 s 是不是 words 的 首字母缩略词 。 如果可以按顺序串联 words 中每个字符串的第一个字符形成字符串 s ,则认为 s 是 words 的首字母缩略词。例如,“ab” 可以由 [“a…...
ClickHouse(二十一):Clickhouse SQL DDL操作-临时表及视图
进入正文前,感谢宝子们订阅专题、点赞、评论、收藏!关注IT贫道,获取高质量博客内容! 🏡个人主页:含各种IT体系技术,IT贫道_Apache Doris,大数据OLAP体系技术栈,Kerberos安全认证-CSDN博客 &…...
redis乐观锁+启用事务解决超卖
乐观锁用于监视库存(watch),然后接下来就启用事务。 启用事务,将减库存、下单这两个步骤,放到一个事务当中即可解决秒杀问题、防止超卖。 但是!!!乐观锁,会带来" …...
智能画笔:如何利用AI绘画API打造独特的创作风格
在当今数字化时代,人工智能的迅猛发展正深刻地影响着各个领域,艺术创作也不例外。AI绘画 API 作为一种创新的工具,为艺术家提供了独特的机会,使他们能够在创作过程中借助人工智能技术,打造出独具个性的创作风格。本文将…...
ElasticSearchConfig
1. 添加配置 <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId></dependency>2. es 配置信息 import org.apache.http.HttpHost; import org.apache.http.auth.Au…...
解决vant组件 van-dialog造成的页面闪动问题
解决方案:该问题是因为van-dialog默认是scale,将这个属性改为fade即可...
SpringBoot内嵌Tomcat连接池分析
文章目录 1 Tomcat连接池1.1 简介1.2 架构图1.2.1 JDK线程池架构图1.2.2 Tomcat线程架构 1.3 核心参数1.3.1 AcceptCount1.3.2 MaxConnections1.3.3 MinSpareThread/MaxThread1.3.4 MaxKeepAliveRequests1.3.5 ConnectionTimeout1.3.6 KeepAliveTimeout 1.4 核心内部线程1.4.1 …...
分布式协调服务中的几个常见算法
分布式协调服务中的几个常见算法包括: 1. 选主算法 用于从多个节点中选举出一个节点作为主节点或者领导者,常见的算法有Bully算法、Ring算法等。 2. 原子广播算法 用于向分布式系统中的所有节点广播消息,保证所有节点都可以收到消息,典型的两阶段提交协议实现了原子广播。…...
易服客工作室:Houzez主题 - 超级房地产WordPress主题/网站
Houzez主题是全球流行的房地产经纪人和公司的WordPress主题。 Houzez Theme是专业设计师创造一流设计的超级灵活起点。它具有您的客户(房地产经纪人或公司)甚至可能做梦也想不到的功能。 网址:Houzez主题 - 超级房地产WordPress主题/网站 - …...
mysql通过binlog日志恢复误删数据
1、先查看binlog功能是否开启 show variables like %log_bin%;log_bin为ON说明可以使用binlog恢复,如果为OFF说明没有开启binlog。 2、删除部分数据做测试 3、查找binlog文件位置 show variables like %datadir%;cd /var/lib/mysqlls -l删除数据时间是在文件154与…...
Istio入门体验系列——基于Istio的灰度发布实践
导言:灰度发布是指在项目迭代的过程中用平滑过渡的方式进行发布。灰度发布可以保证整体系统的稳定性,在初始发布的时候就可以发现、调整问题,以保证其影响度。作为Istio体验系列的第一站,本文基于Istio的流量治理机制,…...
CSS行内,内部,外部以及优先级
1.内联样式表: 将样式编写到style标签里 <style>.context {color: red;} </style> 2. 行内样式: 在 HTML 标签中使用 style 属性设置 CSS 样式 <div style"font-size: 18px;">行内样式</div> 3.外联样式࿱…...
LCA——最近公共祖先
LCA问题是指在一棵树中找到两个节点的最近公共祖先。最近公共祖先是指两个节点在树中的最近的共同祖先节点。例如,在下面这棵树中,节点 6 6 6和节点7的最近公共祖先是节点 3 3 3。 1/ \2 3/ \ / \4 5 6 7解决LCA问题的方法有很多种ÿ…...
游戏开发与硬件结合,开启全新游戏体验!
游戏与硬件的结合可以通过多种方式实现,从改善游戏体验到创造全新的游戏玩法。以下是一些常见的游戏与硬件结合的方式: 虚拟现实(VR)和增强现实(AR)技术:VR和AR技术使玩家能够沉浸式地体验游戏…...
测试框架pytest教程(4)运行测试
运行测试文件 $ pytest -q test_example.py 会运行该文件内test_开头的测试方法 该-q/--quiet标志使输出保持简短 测试类 pytest的测试用例可以不写在类中,但如果写在类中,类名需要是Test开头,非Test开头的类下的test_方法不会被搜集为用…...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...
