草庐IT

Kotlin快速上手

komine 2023-03-28 原文

一、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.2.2 构造函数私有化

如果不想类外部访问到类的构造函数,可以使用 private constructor来修饰主构造函数

class ListDialog<T>private constructor(context: Context) :Dialog(context) {

}

2.3继承

如果想让一个类可以被其他类继承,需要在类的声明之前加上open关键字,使用:冒号来继承

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

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

待更新...

有关Kotlin快速上手的更多相关文章

  1. ruby - 如何以表格格式快速打印 Ruby 哈希值? - 2

    有没有办法快速将表格格式的ruby​​哈希打印到文件中?如:keyAkeyBkeyC...1232343451253474456...其中散列的值是不同大小的数组。还是使用双循环是唯一的方法?谢谢 最佳答案 试试我写的这个gem(在表中打印散列、ruby对象、ActiveRecord对象):http://github.com/arches/table_print 关于ruby-如何以表格格式快速打印Ruby哈希值?,我们在StackOverflow上找到一个类似的问题:

  2. 电脑启动后显示器黑屏怎么办?排查下面4个问题,快速解决 - 2

    电脑启动出现显示器黑屏是一个相当常见的问题。如果您遇到了这个问题,不要惊慌,因为它有很多可能的原因,可以采取一些简单的措施来解决它。在本文中,小编将介绍下面4种常见的电脑启动后显示器黑屏的原因,排查这些原因,快速解决! 演示机型:联想Ideapad700-15ISK-ISE系统版本:Windows10一、显示器问题如果出现电脑启动后显示器黑屏的情况。那么首先您需要检查一下显示器是否正常工作。您可以通过更换另一个显示器或将当前显示器连接到另一台计算机来检查显示器是否存在问题。如果问题仍然存在,那么您可以排除显示器故障的可能性。 二、显卡问题如果您的电脑配备了独立显卡,那么显卡故障也可能是导致电脑

  3. ruby - 使单元测试快速失败以进行突变测试 - 2

    mutationtesting遇到一个问题是它很慢,因为默认情况下您会为每个生成的突变执行完整的测试运行(测试文件或一组测试文件)。加快突变测试的一种方法是,一旦遇到单一故障(但仅在突变测试期间),就停止对给定突变体的测试运行。更好的做法是让变异测试者记住杀死最后一个变异体的第一个测试是什么,并将其首先交给下一个变异体。ruby中是否有任何东西可以做这些事情,或者我最好的选择是开始猴子修补?(是的,我知道单元测试应该很快。显示所有失败的测试在突变测试之外很有用,因为它不仅可以帮助您识别出问题,还可以查明哪里出了问题)编辑:我目前正在对测试/单元使用heckle。如果测试/单元不可能记住

  4. ruby - 使用和不使用 Rails 的快速 (Rspec) 测试 - 2

    我有两个类:1.Sale是ActiveRecord的子类;它的工作是将销售数据持久保存到数据库中。classSale2.SalesReport是一个标准的Ruby类;它的工作是生成和绘制有关销售的信息。classSalesReportdefinitialize(start_date,end_date)@start_date=start_date@end_date=end_dateenddefsales_in_durationSale.total_for_duration(@start_date,@end_date)end#...end因为我想使用TDD并且我希望我的测试运行得非常快,所

  5. ruby - 快速FTP服务器 - 2

    我正在寻找一个快速、无需配置的FTP服务器。完全像Serve的东西或Rack_dav,但对于FTP,它可以通过运行命令来发布文件夹。是否有gem或其他东西可以做这样的事情?解决方案基于Wayne的ftpdgem,我创建了一个快速且易于使用的gem,名为Purvey. 最佳答案 ftpdgem支持TLS,并带有文件系统驱动程序。与em-ftpd一样,您提供一个驱动程序,但该驱动程序不需要做太多事情。这是一个最低限度的FTP服务器,它接受任何用户名/密码,并提供临时目录中的文件:require'ftpd'require'tmpdir'c

  6. ruby - 快速解决字谜 - 2

    给定两个字符串,我想确定它们是否是彼此的变位词。这是我想出的解决方案:#outputmessagesdefanagramputs"Anagram!"exitenddefnot_anagramputs"Notananagram!"exitend#mainmethodif__FILE__==$0#readtwostringsfromthecommandlinefirst,second=gets.chomp,gets.chomp#specialcase1not_anagramiffirst.length!=second.length#specialcase2anagramiffirst==s

  7. 线性代数让我想想:快速求三阶矩阵的逆矩阵 - 2

    快速求三阶矩阵的逆矩阵前言一般情况下,我们求解伴随矩阵是要注意符号问题和位置问题的(如下所示)A−1=1[  ][−[  ]−[  ]−[  ]  −[  ]]=A−1=1[  ][   M11−[M12]   M13−[M21]   M22−[M23]     M31−[M32]   M33]⊤\begin{aligned}&A^{-1}=\frac{1}{[\\]}\left[\begin{array}{cccccc}&-[\\]&\\-[\\]&&-[\\]\\\\&-[\\]&\\\end{array}\right]=\\\\&A^{-1}=\frac{1}{[\\]}\left[\b

  8. 火爆的ChatGPT快速学成,要看哪些书? - 2

    以前我们经常打趣说:***,你out了!当然了,玩笑成分居多。但是如果作为一名技术人员,现在还没有听说过ChatGPT,那么你可能真的“out”了。比尔·盖茨说,ChatGPT的重要性堪比互联网的发明,甚至它“将改变我们的世界”。ChatGPT得到科技界大佬的如此推崇,那么,ChatGPT到底是什么?ChatGPT是2022年11月底,美国OpenAI公司推出的一款人工智能聊天机器人。两个月后,ChatGPT的月活用户已经突破1亿,成为有史以来增长速度最快的消费者应用程序。ChatGPT功能极其强大,它能够通过学习和理解人类的语言进行对话,还能根据上下文进行互动,实现像人类一样的聊天交流。除了

  9. ruby - Ruby 语言中的快速排序 - 2

    我正在尝试在ruby​​中实现快速排序,但卡在如何在pivot的第一个分区之后递归调用。请帮助我了解如何进行,并让我知道到目前为止我的编码风格是否良好。classQuickSort$array=Array.new()$count=0defadd(val)#addingvaluestosorti=0whileval!='000'.to_i$array[i]=val.to_ii=i+1val=gets.to_iendenddeffirstsort_aka_divide(val1,val2,val3)#firstpartition$count=$count+1@pivot=val1@left

  10. ruby - 缓慢的 Ruby 正则表达式通过奇怪的变化变得快速 - 2

    我一直在调试网站以查找页面加载时间过长的根源,并将其缩小为用于从文本中提取URL的正则表达式:/(?:([\w+.-]+):\/\/|(?:www\.))[^\s在一大块文本上运行大约需要3秒。我发现如果我将第一个子句的逆语句添加到正则表达式((?:[^\w+.-]|^))的开头,它几乎会立即运行:/(?:[^\w+.-]|^)(?:([\w+.-]++):\/\/|(?:www\.))[^\s在我看来,添加的子句根本不应该影响正则表达式,因为没有什么可以导致该子句失败(因为这些字符将与“[\w+.-]++”子句匹配)。为什么这会使正则表达式运行得更快?编辑有些人要求提供我正在尝试做的

随机推荐