Kotlin快速上手

来源:https://www.cnblogs.com/komine/archive/2022/04/14/16147147.html
-Advertisement-
Play Games

一、Kotlin基礎 1.數據類型聲明 在Kotlin中要定義一個變數需要使用var關鍵字 //定義了一個可以修改的Int類型變數 var number = 39 如果要定義一個常量可以使用val關鍵字,等價於Java的final關鍵字. val name = "miku" //給val定義的常量再 ...


一、Kotlin基礎

1.數據類型聲明

在Kotlin中要定義一個變數需要使用var關鍵字

//定義了一個可以修改的Int類型變數
var number = 39

如果要定義一個常量可以使用val關鍵字,等價於Java的final關鍵字.

val name = "miku"

//給val定義的常量再次賦值就會提示錯誤
name = "ミク"

在Kotlin中要聲明一個數據類型必須要使用var或者val來定義.

2.數據類型

Kotlin的數據類型分為基本數據類型和引用數據類型.

基本數據類型:Boolean、Number、Char

引用類型:可空類型、Object、數組類型

Kotlin中的Number類型泛指所有跟數字有關的類型,int、float、double、long

//java.lang.Integr  Int--->int
var intNumber:Number = 39

//java.lang.Float   Float--->float
var floatNumber:Number = 39.0f

//java.lang.Double   Double--->double
var doubleNumber:Number = 39.000000000000000

//java.lang.Long   Long--->long
var longNumber:Number = 39L

2.1.Kotlin預定義的基本數據類型

var intType:Int = 39 //int

var shortType:Short = 39 //short

var byteType:Byte = 0 //byte

var boolType:Boolean = true //boolean

var stringType:String = "miku" //String

var floatType:Float = 39f //float

var doubleType:Double = 39.0000000000 //double

var longType:Long = 39L //long

var numberType:Number = 39 //Integr、Float、Double、Long

var charType:Char = '0' //char

字元串拼接,通過${}直接引用變數,不再需要引號 + 引號的方式

val name = "komine"
val text = "私の名前は${name}と申します。"

print(text)

2.2.元組

元組是一個固定長度,且不能被修改的數據結構

//二階元組
var person1 = Pair("komin",16)

//三階元組
var person2 = Triple("komine",18,"女")

person2.first //第一個元素的值
person2.second  //第二個元素的值
person2.third   //第三個元素的值
  

Kotlin的元組其實就是一個泛型對象的封裝.通過反編譯生成的.class文件可以看出,二階元組其實是對應Pair類,

三階元組其實是對應Triple類. first、second、third分別對應getFirst()、getSecond()、getThrid()方法.

如果用Java來實現的話差不多就是下麵這個樣子,可以看到,元組不過是Kotlin在源碼階段提供的一種更方便的語法而已.

public class MyPair<First,Second> {

    private final First mFirstValue;
    private final Second mSecond;

    public MyPair(First first, Second second){
        this.mFirstValue = first;
        this.mSecond = second;
    }

    public First getFirst() {
        return mFirstValue;
    }

    public Second getSecond() {
        return mSecond;
    }
}

2.3.可空類型

Kotlin定義了一種可以為空的數據類型,只有聲明為可空類型的變數才能將null賦值於它.預設聲明的類型全部都是非空類型.

var str:String? = null  //在類型的後面添加?表示該類型可空

print(str?.length)  //通過?.方式來訪問可空類型的成員方法或變數,如果str是null則後面的調用會返回null,不會報錯

//如果你明確知道,str在某個時候肯定不為空,可以通過!!操作該變數,但如果str為空則會拋出空指針異常
print(str!!.length)

2.4.數組

在Kotlin中定義一個數組非常簡單.調用arrayOf()即可創建一個數組.

var names = arrayOf("miku","rin","luka")
var numbers = arrayOf(16,14,17)

//跟Java一樣,也可以通過[下標]的方式訪問數組的元素
print(names[0])

//創建一個指定長度的數組,值為null
var fixedArray = arrayOfNulls<Int>(39)

//創建一個空數組
var emptyArray = emptyArray<Int>()

2.5.集合

Kotlin的集合分為可變集合和不可變集合.可變集合都是由Mutable開頭的.

可變集合

//MutableList集合,該集合可以包含相同元素
var mutableList = mutableListOf("miku","rin","luka")

//鍵值對,包含Key和Value的集合
var mutableMap = mutableMapOf<String,String>()
var linkedHashMap = linkedMapOf<String,String>() //等價mutableMap

//MutableSet集合,該集合不會出現相同的元素,如果集合已經包含某個值,添加的時候會忽略添加操作
var mutableSet = mutableSetOf<Object>()
var linkedSet = linkedSetOf<String>() //等價mutableSet

不可變集合

//List集合,無法進行添加操作
var list = listOf("miku","rin","luka")

//Map集合,無法進行添加操作
var map = mapOf(Pair("miku",16))
var linkedMap = 

//Set集合,無法進行添加操作
var set = setOf<Int>(0,1,2,3,4,5,6,7,8,9)

2.5.1擴展方法

toList() 返回一個不可變List集合

toMap() 返回一個不可變的Map集合

toSet() 返回一個不可變的Set集合

2.5.2集合操作

類似.Net中的Linq查詢

any 判斷集合中是否有滿足條件的元素

var mutableList = mutableListOf("miku","rin","luka")

val result:Boolean = mutableList.any(){
    it == "miku" //有一個元素的值為miku
}

all 判斷集合中的所有元素是都否滿足條件

var mutableList = mutableListOf("miku","rin","luka")

val result:Boolean = mutableList.all(){
    it.isNotEmpty() //元素的長度大於0
}

none 判斷集合中的所有元素是否都不滿足條件,滿足則返回true

var mutableList = mutableListOf("miku","rin","luka")

val result:Boolean = mutableList.none(){
    it.isNotEmpty()  //元素的長度等於0  false
}

count 返回滿足條件的元素個數,類似sql中的select count(*) from table where xx = xx

var mutableList = mutableListOf("miku","rin","luka")

val result: Int = mutableList.count {
    it == "miku"  //返回集合中元素值為miku的元素個數
}

reduce 從第一個元素到最後一個元素的累加

val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
val result: Int = numbers.reduce() {
    sum: Int, i -> sum + i  //sum:聲明一個用於接收累加結果的變數 i->:迴圈每一個元素,sum + i:累加每個元素到sum
}

reduceRight 從最後一個元素到第一個元素的累加

val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
val result: Int = numbers.reduceRight() {
    sum: Int, i -> sum + i
}

fold 跟reduce類似,不過可以設置初始化,從初始值開始累加

val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
val result: Int = numbers.fold(10){
    sum, i -> sum + i
}

foldRight...

sumOf 返回集合中所有元素的總和,該集合的元素必須是Number類型

val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
val result = numbers.sumOf{
    it
}

dropWhile 去除滿足條件的元素,直到不滿足為止,返回剩餘元素的集合

val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
val result = numbers.dropWhile {
    it < 5
}

filter 過濾不滿足條件的元素,返回滿足元素的新集合

val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
val result = numbers.filter {
    it < 5
}

filterNot 過濾滿足條件的元素,返回不滿足元素的新集合

val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
val result = numbers.filterNot {
    it < 5
}

take 返回從第一個元素開始的N個元素

val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
val result = numbers.take(5)   //{1,2,3,4,5}

takeLast 返回從最後一個元素開始的N個元素

...

takeWhile 返回從第一個元素開始符合給定條件的元素

val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
val result = numbers.takeWhile {
    it > 0
}

drop 返回去掉N個元素之後的列表

val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
val result = numbers.drop(1)

dropLastWhile 返回從最後一個元素開始,去掉滿足條件的元素

val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
val result = numbers.dropLastWhile {
    it > 5
}

slice 保留指定下標對應的元素

val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
val result = numbers.slice(listOf(1,2,3))

map 將集合中的元素通過某種方法轉換後,返回一個新集合

val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
val result = numbers.map {
    val diff = 10
  
    it * diff
}

後續更新...

2.6.類型轉換

Kotlin通過as關鍵字將一個類型轉換為另一個類型.

var numberType:Number = 39
var intType:Int = numberType as Int

Kotlin可以通過 is 關鍵字自動完成裝箱的操作.

open class GameConsole{

}

class PS4 : GameConsole() {

}

class NintendoSwitch : GameConsole() {
    public val version = "10.0"
}

fun main(args: Array<String>) {
    val gameConsoles = arrayOf(PS4(),NintendoSwitch())
    val gameConsole = gameConsoles[1]

    //會自動完成裝箱操作,在當前調用範圍內將gameConsole識別NitendoSwitch,可以直接訪問對象的成員,不需要手動轉換
    if(gameConsole is NintendoSwitch){
        print(gameConsole.version)
    }
}

3.運算符

Kotlin特有的運算符有===、!==

3.1.恆等和非恆等

判斷兩個對象之間的地址是否相等

var obj1 = Object()
var obj2 = Object()

if(obj1 === obj2){
    println("恆等")
}

if(obj1 !== obj2){
    println("非恆等")
}

3.2.位運算

只有Int和Long類型可以使用.

val i:Int = 10
val j:Int = 20

val result = i shl j //有符號左移
result = i shr j //有符號右移
result = i ushr  //無符號右移
result = i and j  //按位與
result = i or j  //按位或
result = i xor  //按位異或
result = i inv j  //按位取反

3.3.區間運算符

表示某個值是否在某個範圍或者集合之中.

//i >=0 && i <= 100
if(i in 0..100){
    print(i)
}

數組或者集合是否包含某個值

val names = arrayOf("miku","rin","luka")
if("miku" in names){
    print("包含")
}

4.條件語句

when是Kotlin提供類似Java中Switch的條件語句.它能做到Switch能做到的所有事,並且還提供了更方便的語法.

fun test(i:Int){
    when(i){

        // case 1
        1 ->{

        }

	//case 2
        2 -> {

        }

 	//i >= 3 && i <= 9
        in 3..9 ->{

        }

	//default
        else ->{

        }
    }
}

when如果不提供參數也可以當作if elseif使用

5.迴圈語句

跟Java的使用差別不大,一般配合區間運算符in來更簡便的使用

val names = arrayOf("miku","rin","luka")
for (name in names){
    println(name)
}

//遍曆數組或集合帶索引
for ((index,name) in names.withIndex()){
  
}

val i = 0
for (i in 0..99){  //i = 0;i <= 99;i++
    println(i)
}

var i = 10
while (i > 0){
    println(i)
    i--
}

do {
    i--
    println(i)
}while (i > 0)

//foreach
val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
numbers.forEach{ it ->
    println(it)
}

//foreach 帶索引
val numbers = mutableListOf(1,2,3,4,5,6,7,8,9)
numbers.forEachIndexed{index, i ->  
    println("index[${index}] = $i")
}

6.函數

Kotlin中定義函數使用fun關鍵字.如果方法不需要返回值可以不寫,或者寫Unit

fun sum(number1:Int,number2:Int):Int{
    return number1 + number2
}

6.1預設參數

Kotlin中添加了預設參數的支持,當一個方法指定了參數的預設值,則調用的時候可以不提供該參數的值.

要使用預設參數,在參數的後面添加=進行賦值操作.

fun sum(number1:Int,number2:Int = 0):Int{
    return number1 + number2
}

6.2可變參數

和Java一樣,Kotlin也提供可變參數的支持,使用vararg關鍵字聲明可變參數

fun sum(vararg number:Int){
    //number在使用的時候其實是一個數組類型的變數,可以調用數組的一些方法
}

6.3Lambda表達式

Lambda表達式可以看作是一個匿名的函數.

var execute:(Int,Int) -> Int = {x,y ->
    x * y
}

println(execute(10,10))

如果函數只有一個參數時可以省略不寫,這個時候用it來表示

var execute:(String) -> String = {
    it
}

println(execute("komine"))

6.4高階函數

Kotlin支持將函數作為參數或者返回值,包含這樣操作的函數稱為高階函數.將函數作為參數時使用雙冒號::來傳遞.

fun main(args: Array<String>) {
   call(::method)
}

fun call(m:(number:Int) -> Int){
    println(m(39))
}

fun method(number:Int):Int{
    return number * number
}

也可以使用Lambda表達式來表示一個匿名參數.

call{number: Int -> return@call number * number }

Kotlin本身也提供了一些高階函數供我們使用,比如apply函數,在Android中初始化變數可以這樣寫.

var paint = Paint().apply {
    this.isAntiAlias = true
    this.color = Color.BLACK
    this.style = Paint.Style.STROKE
    this.strokeWidth = 10f
}

6.5內聯函數

Kotlin支持內聯函數,跟C++的內聯函數作用一致,因為函數的執行有壓棧和出棧的步驟,會帶來一定的開銷.

在將函數聲明為內聯函數的時候,在編譯的時候,編譯器會在所有調用函數的地方,將函數調用直接替換成函數體的內容.

一般來說,內聯函數中的嵌套邏輯不能太複雜,C++的內聯函數是否替換是由編譯器決定的,Kotlin會按照inline關鍵直接替換.

通過反編譯生成的class文件可以看到,內聯函數就是直接將有函數調用的地方,直接替換成函數體的內容.

fun main(args: Array<String>) {
    test()
}

inline fun test(){
    for (i in 0..99){
        println(i)
    }
    for (i in 0..99){
        println(i)
    }
    for (i in 0..99){
        println(i)
    }
    for (i in 0..99){
        println(i)
    }
    for (i in 0..99){
        println(i)
    }
    for (i in 0..99){
        println(i)
    }
}

反編譯結果

如果函數的參數中有函數參數類型或者Lambda表達式,也可以使用noinline關鍵字指定不參數內聯的函數.

crossinline關鍵字待補充...

二、Kotlin進階

1.協程

協程是跑線上程上的產物,它擁有自己的棧記憶體和局部變數,被稱為輕量級Thread.它的內部實現是由編譯器來完成的.

官方文檔說明

在使用協程之前,需要添加依賴

implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1'

簡單用法

GlobalScope.launch(context = Dispatchers.Default, start = CoroutineStart.DEFAULT) {
    //延時1.5秒
    delay(1500L)
    println("當前線程:" + Thread.currentThread().name)
    println("World")
}
println("Hello,")
println("當前線程:" + Thread.currentThread().name)
Thread.sleep(3000L)

context:協程的上下文,這裡設置的是CoroutineDispatch協程運行的線程調度器,它有四種線程模式:

Dispatchers.Default //預設

Dispatchers.IO //工作在其他線程

Dispatchers.Main //主線程

Dispatchers.Unconfined //不指定就是在當前線程,kotlinx.coroutines.DefaultExecutor

也可以自己創建一個協程上下文,這個上下文也可以理解為協程所運行在的線程.

val context = newSingleThreadContext("single")

start:啟動模式,預設是CoroutineStart.DEFAULT,就是創建之後就會啟動

CoroutineStart.DEFAULT

CoroutineStart.ATOMIC

CoroutineStart.UNDISPATCHED

CoroutineStart.LAZY 懶載入模式,它會返回一個Job對象,你可以手動開啟它.

val job = GlobalScope.launch(context = Dispatchers.Default, start = CoroutineStart.LAZY) {
    //延時1秒
    delay(1500L)
    println("當前線程:" + Thread.currentThread().name)
    println("World")
}
println("Hello,")
println("當前線程:" + Thread.currentThread().name)

job.start()

Thread.sleep(3000L)

GlobalScope.async 帶返回值

suspend fun main(args: Array<String>) {
    val result = GlobalScope.async {
        delay(1000L)
        return@async "async"
    }

    println(result.await())
    Thread.sleep(3000)
}

async會阻塞當前協程,會等待當前協程執行完畢,調用await()的函數需要使用suspend關鍵字修飾.

協程的掛起,suspend表示當前協程被掛起.

fun main(args: Array<String>) {
    GlobalScope.launch {
        //get方法是被suspend修飾的,表示調用時會將當前協程掛起
        val str = get()
        //會等待get()執行完畢才會繼續執行
        printStr(str)
    }
    //防止進程結束
    Thread.sleep(3000L)
}

suspend fun get():String{
    println("get()正在執行..")
    delay(1000)

    return "data"
}

suspend fun printStr(str:String){
    println(str)
}

協程之間也可以嵌套,調用await會阻塞外部協程,代碼還是會按順序運行

fun main(args: Array<String>) {
    GlobalScope.launch {
        val str = GlobalScope.async {
            return@async get()
        }.await()

        GlobalScope.launch{
	    printStr(str)
        }
    }
    //防止進程結束
    Thread.sleep(3000L)
}

suspend fun get():String{
    println("get()正在執行..")
    delay(1000)

    return "data"
}

suspend fun printStr(str:String){
    println(str)
}

待補充...

2.面向對象

2.1類的聲明

和很多語言一樣,Kotlin使用class關鍵字來聲明一個類.

class Person{

}

2.1.1內部類

class Person{
    //內部類的聲明使用inner關鍵字修飾
    inner class Info{
  
    }
}

要實例內部類需要先實例化主類

val person = Person("miku")
val info = person.Info()

2.1.2數據類

通過data class 修飾的類稱為數據類,數據類必須提供一個有參的構造函數.數據類一般不定義方法.

data class MyData(val height:Float,val weight:Float,val money:Float){

}

2.1.3枚舉類

跟Java的枚舉類使用基本相同.

enum class DirectionEnum{
    East{
        override fun move() {

            //name:當前枚舉常量的名稱
            //ordinal:當前枚舉常量的值
	    println("name$name")
            println("value:$ordinal")
        }
    },
    South{
        override fun move() {

        }
    },
    West{
        override fun move() {

        }
    },
    North{
        override fun move() {
  
        }
    };
    abstract fun move();
}

2.1.4密封類

emm...不知道怎麼用,後面補充

2.1.5抽象類

使用abstract關鍵字聲明一個抽象類

open abstract class Person(name:String, age:Int){
  
}

2.2構造函數

Kotlin的構造函數可以直接寫在類名的後面,稱為主構造函數,這樣定義的構造函數是沒有方法體的,要執行初始化操作

可以使用init代碼塊.

open class Person(name:String, age:Int){

    init {
        println("主構造函數執行...")
        println("name:${name},age = $age")
    }
}

2.2.1 副構造函數

通過constructor定義的構造函數稱為副構造函數,需要間接調用主構造函數進行初始化

fun main(args: Array<String>) {
    val person = Person("miku")
}

open class Person(name:String, age:Int){

    init {
        println("主構造函數執行...")
        println("name:${name},age = $age")
    }

    //副構造函數需要間接調用主構造函數通過this關鍵字
    constructor(name:String) : this(name,16) {
        println("副構造函數執行...")
    }
}

2.3繼承

如果想讓一個類可以被其他類繼承,需要在類的聲明之前加上open關鍵字,使用:冒號來繼承

open class Person{
    open fun take(){}
}

class Student : Person() {

}

如果子類想重寫父類定義的方法,該方法必須是open關鍵字修飾的方法,抽象方法的修飾符預設是open.

2.4靜態成員

Kotlin沒有提供static關鍵字,如果想實現Java那樣的靜態成員調用可以使用companion object代碼塊來定義靜態成員.

在Kotlin中稱為伴生對象,用伴生對象的成員來代替靜態成員.

class PS4{
    companion object{
        val FIRMWARE_VERSION:Float = 10.0f
        fun boot(){
            println("boot...")
        }
    }
}

跟Java一樣,然後通過類名調用靜態成員

PS4.boot()
PS4.FIRMWARE_VERSION

2.5介面

使用interface來聲明一個介面.與Java的用法並無二致

interface Callback{
    fun onSuccess()
    fun onFailed()
}

3.泛型

基本使用和Java一致

class Data<T>(private val data:T){
    fun get():T{
        return data
    }
}
val data1 = Data("String")
println(data1.get())

val data2 = Data(16)
println(data2.get())

3.1out和in關鍵字

Kotlin中使用out和in來代替? extends 和? super使用,具體用法跟Java是類似的.

fun main(){
    val ps4List = mutableListOf<PS4>()

    setGameConsoles(ps4List)
  
    val gameConsoles = getGameConsoles()
    for (gameConsole in gameConsoles){
        val ps4 = gameConsole as PS4
        ps4.play()
    }
}

// out ----> ? extends GamesConsole
fun setGameConsoles(gamConsoles:MutableList<out GameConsole>){
   
}

//in -----> ? super PS4
fun getGameConsoles():MutableList<in PS4>{
    val gameConsoles = mutableListOf<GameConsole>()
    gameConsoles.add(PS4())
    gameConsoles.add(PS4())
    return gameConsoles
}

open class GameConsole{
    open fun play(){

    }
}

class PS4 : GameConsole(){
    override fun play() {
        println("ps4 play...")
    }
}

class NintendoSwitch : GameConsole(){
    override fun play() {
        println("ns play...")
    }
}

4.委托

其實就是代理設計模式.

4.1委托的使用場景

Java中的代理模式實現

//支付介面
public interface IPay {
    void pay();
}

//支付寶支付
public class AliPay implements IPay{
    private float mMoney;
    public AliPay(float money){
        mMoney = money;
    }

    @Override
    public void pay() {
        Log.d("Alipay","支付寶支付" + mMoney + "元...");
    }
}

//微信支付
public class WeChatPay implements IPay{
    private float mMoney;
    public WeChatPay(float money){
        mMoney = money;
    }

    @Override
    public void pay() {
        Log.d("WeChatPay","微信支付" + mMoney + "元...");
    }
}

//代理對象
public class ProxyPay implements IPay{
    private IPay mPay;
    public ProxyPay(IPay pay){
        mPay = pay;
    }

    @Override
    public void pay() {
        mPay.pay();
    }
}

Kotlin的代理模式實現

interface IPay{
    fun pay()
}

class Alipay(private val money:Float) :IPay{
    override fun pay() {
        println("支付寶支付$money...")
    }
}

class WeChatPay(private val money: Float) :IPay{
    override fun pay() {
        println("微信支付$money...")
    }
}

class PayDelegate(private val play:IPay) :IPay by play{
    //什麼都不需要做,系統幫我們完成一系列操作
}

可以看出,Kotlin的委托其實就是簡化了代理模式的實現過程.

4.2屬性委托

將屬性的賦值操作交給其他類來代理.可以通過其他類來統一控制屬性的取值,合法性等等操作.

基本使用

//聲明一個介面,不一定要介面也可以是一個類
interface IPropertyDelegate

class PS4 :IPropertyDelegate{
    var version:String by DataDelegate()
}

class NintendoSwitch :IPropertyDelegate{
    var version:String by DataDelegate()
}

class DataDelegate {
    private var version:String = ""
    operator fun setValue(thisRef: IPropertyDelegate, property: KProperty<*>, value: String) {
        this.version = value
    }

    operator fun getValue(thisRef: IPropertyDelegate, property: KProperty<*>): String {
        return this.version
    }
}

當給PS4或者NintendoSwitch對象的version賦值的時候,就會去到DataDelegate對象的setValue()方法,達到統一賦值的操作,相同的操作不需要在每個類都寫一次

val ps4 = PS4()

ps4.version = "7.55"
println(ps4.version)

val ns = NintendoSwitch()

ns.version = "13.0"
println(ns.version)

5.其他

5.1擴展函數

給某個類添加一個擴展函數,其效果跟成員函數調用一致.一般定義到一個統一的文件中,不需要先定義一個類型,直接寫就好

//給String擴展了一個first方法
fun String.first():Char{
    return this[0]
}

println("komine".first())

5.1擴展屬性

給某個類添加一個擴展屬性

val Int.dp:Int
    get(){
        //簡單模擬一下,開發中不是這麼計算的
        return this * 1.5f.toInt()
    }

比如給Int類型添加了一個dp的擴展屬性,可以將int值轉換為對應的dp

val width = 39.dp

待更新...


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 鏡像下載、功能變數名稱解析、時間同步請點擊 阿裡雲開源鏡像站 一、Zabbix 簡介 Zabbix 可以用來監控各種網路參數,來保證伺服器和系統的安全運行。並且 Zabbix 還提供了靈活的通知機制,以此來讓系統管理員快速定位/解決存在的各種問題。是一個基於 Web 界面提供的分散式系統監控以及網路監控功能 ...
  • 1. 什麼是資料庫 資料庫是“按照數據結構來組織、存儲和管理數據的倉庫”。是一個長期存儲在電腦內的、有組織的、可共用的、統一管理的大量數據的集合。簡單的來說就像是一個大型的衣櫃,你所有春夏秋冬的衣服都被統一放在了一個衣櫃里,然後分類,分季節的有序擺放好。資料庫的優點重點在於體量足夠的大,一般的數據 ...
  • 12月21日,在第十一屆中國資料庫技術大會(DTCC)2020數據風雲獎評選活動中,華為雲資料庫GaussDB(openGauss)和金融行業核心資料庫上雲解決方案分別榮獲“年度最佳創新產品獎”、“年度最佳創新解決方案獎”。 DTCC2020是由IT168 旗下 ITPUB 企業社區平臺主辦的頂級數 ...
  • 近年來,雲計算已成為主流,企業從自身利益出發,或是不願意被單一雲服務商鎖定,或是業務和數據冗餘,或是出於成本優化考慮,會嘗試將部分或者全部業務從線下機房遷移到雲或者從一個雲平臺遷移到另一個雲平臺,業務遷移涉及到數據的遷移。正好 JuiceFS 已經對接了各種對象存儲的 API ,也實現了數據同步的邏 ...
  • 本文介紹瞭如何使用 SQL 的 SELECT 語句來檢索單個表列、多個表列以及所有表列。也介紹瞭如何返回不同的值以及如何註釋代碼。 一、SELECT 語句 正如 學習 SQL 之前需要瞭解的基礎知識 所述,SQL 語句是由簡單的英語單詞構成的。這些單詞稱為關鍵字,每個 SQL 語句都是由一個或多個關 ...
  • 說起雲會議大家第一想起的就是疫情期間,上網課也好,網上辦公也好等等。在疫情到來之前線上會議就已經有了雛形但是並不完善,但是疫情開始之後,線上會議蓬勃發展,各種雲會議應用而生。雲會議得到了空前的發展,那麼當我們需要一場高質量的雲會議時應該怎麼選擇呢? 雲會議帶給我們體驗最重要的三點:夠清晰、夠流暢、夠 ...
  • 本文為 SQL 初學者介紹了 SQL 究竟是什麼,以及它能做什麼事情。因為 SQL 是用來與資料庫打交道的,所以,我們也介紹了一些基本的資料庫術語。 一、資料庫基礎 你正在讀這這一篇文章,這表明你需要以某種方式與資料庫打交道。SQL 正是用來實現這一任務的語言,因此在學習 SQL 之前,你應該對數據 ...
  • 本章目錄 0x00 數據持久化 1.RDB 方式 2.AOF 方式 如何抉擇 RDB OR AOF? 0x01 備份容災 一、備份 1.手動備份redis資料庫 2.遷移Redis指定db-資料庫 3.Redis集群數據備份與遷移 二、恢復 1.系統Redis用戶被刪除後配置數據恢復流程 2.Kub ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...