第10章 Kotlin与Java互操作

Kotlin is 100% interoperable with Java™ and Android™

在前面的章节中,我们已经学习了Kotlin的基础语法、类型系统、泛型与集合类、面向对象与函数式编程等主题,在上一章中我们还看到了Kotlin提供的轻量级并发编程模型:协程的相关内容。

从本章开始到在后面的章节中,我们将进入工程代码的实战。我们将在后面分别介绍Kotlin集成SpringBoot开发服务端Web项目、使用Kotlin开发Android项目,以及使用Kotlin来写前端JavaScript代码的等主题。

Kotlin 的竞争优势在于它并不是完全隔离于 Java 语言。它基本上是可与 Java 100% 互操作的。这样,Kotlin就可以站在整个Java生态巨人的肩上,向着更远大的前程前进。

本章我们就让我们一起来学习下Kotlin与Java的互操作。

Kotlin 调用 Java示例

Kotlin 很像 Java。它长得不像 Clojure 或者 Scala 那么奇怪(承认现实把,这两种语言就是挺奇怪的)。所以我们学 Kotlin 应该很快。这门语言显然就是写给 Java 开发者来用的。

Kotlin 在设计之初就考虑了与 Java 的互操作性。我们可以从 Kotlin 中自然地调用现存的 Java 代码。例如,下面是一个Kotlin调用Java中的Okhttp库的代码:

package com.easy.kotlinimport okhttp3.*
import java.io.File
import java.io.IOException
import java.util.concurrent.TimeUnitobject OkhttpUtils {fun get(url: String): String? {var result: String? = ""val okhttp = OkHttpClient.Builder().connectTimeout(1, TimeUnit.HOURS).readTimeout(1, TimeUnit.HOURS).writeTimeout(1, TimeUnit.HOURS).build()val request = Request.Builder().url(url).build()val call = okhttp.newCall(request)try {val response = call.execute()result = response.body()?.string()val f = File("run.log")f.appendText(result!!)f.appendText("\n")} catch (e: IOException) {e.printStackTrace()}return result}
}

Kotlin调用Java代码跟Groovy一样流畅自如(但是不像Groovy那样“怎么写都对,但是一运行就报错”,因为Groovy是一门动态类型语言,而Kotlin则是一门强类型的静态类型语言)。我们基本不需要改变什么就可以直接使用Java中的API库。

并且在 Java 代码中也可以很顺利地调用 Kotlin 代码:

package com.easy.kotlin;import com.alibaba.fastjson.JSON;/*** Created by jack on 2017/7/14.*/
public class JSONUtils {public static String toJsonString(Object o) {return JSON.toJSONString(o);}public static void main(String[] args) {String url = "http://www.baidu.com";String result = OkhttpUtils.INSTANCE.get(url);System.out.println(result);}
}

因为Kotlin跟Java本是两门语言,所以在互相调用的时候,会有一些特殊的语法。这里的使用Java调用Kotlin的object对象函数的语法就是OkhttpUtils.INSTANCE.get(url), 我们看到这里多了个INSTANCE 。

我们甚至也可以在一个项目中同时使用Kotlin和Java两 种语言混合编程。我们可以在下一章中看到,我们在一个SpringBoot工程中同时使用了Kotlin和Java两种语言进行混合开发。

下面我们来继续介绍 Kotlin 调用 Java 代码的一些细节。

Kotlin使用Java的集合类

Kotlin的集合类API很多就是直接使用的Java的API来实现的。我们在使用的时候,毫无违和感,自然天成:

@RunWith(JUnit4::class)
class KotlinUsingJavaTest {@Test fun testArrayList() {val source = listOf<Int>(1, 2, 3, 4, 5)// 使用Java的ArrayListval list = ArrayList<Int>()for (item in source) {list.add(item) // ArrayList.add()}for (i in 0..source.size - 1) {list[i] = source[i] // 调用 get 和 set}}
}

Kotlin调用Java中的Getter 和 Setter

在Java中遵循这样的约定: getter 方法无参数并以 get 开头,setter 方法单参数并以 set 开头。在 Kotlin 中我们可以直接表示为属性。 例如,我们写一个带setter和getter的Java类:

package com.easy.kotlin;import java.util.Date;/*** Created by jack on 2017/7/14.*/
public class Product {Long id;String name;String category;Date gmtCreated;Date gmtModified;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getCategory() {return category;}public void setCategory(String category) {this.category = category;}public Date getGmtCreated() {return gmtCreated;}public void setGmtCreated(Date gmtCreated) {this.gmtCreated = gmtCreated;}public Date getGmtModified() {return gmtModified;}public void setGmtModified(Date gmtModified) {this.gmtModified = gmtModified;}
}

然后,我们在Kotlin可以直接使用属性名字进行get和set操作:

@RunWith(JUnit4::class)
class ProductTest {@Test fun testGetterSetter() {val product = Product()product.name = "账务系统"product.category = "金融财务类"product.gmtCreated = Date()product.gmtModified = Date()println(JSONUtils.toJsonString(product))Assert.assertTrue(product.getName() == "账务系统")Assert.assertTrue(product.name == "账务系统")Assert.assertTrue(product.getCategory() == "金融财务类")Assert.assertTrue(product.category == "金融财务类")}
}

当然,我们还可以像在Java中一样,直接调用像product.getName()、product.setName(“Kotlin”)这样的getter、setter方法。

调用Java中返回 void 的方法

如果一个 Java 方法返回 void,那么从 Kotlin 调用时中返回 Unit

public class Admin {String name;public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Admin{" +"name='" + name + '\'' +'}';}
}

我们这样调用

val setReturn = admin.setName("root")
println(setReturn)

将输出:

kotlin.Unit

空安全和平台类型

我们知道Java 中的任何引用都可能是null,这样我们在使用 Kotlin调用来自 Java 的对象的时候就有可能会出现空安全的问题。

Java 声明的类型在 Kotlin 中会被特别对待并称为平台类型(platform types )。对这种类型的空检查会放宽,因此它们的安全保证与在 Java 中相同。

请看以下示例:

@RunWith(JUnit4::class)
class CallingJavaNullSafe {@Test fun testCallingJavaNullSafe() {val product = Product()// product.name = nullproduct.category = "金融财务类"product.gmtCreated = Date()product.gmtModified = Date()println(JSONUtils.toJsonString(product))val name = product.nameprintln("product name is ${name}")val eqName = name == "账务系统"println(eqName)name.substring(1)}
}

上面的代码可以正确编译通过。Kotlin编译器对来自Java的空值name(平台类型)放宽了空检查name.substring(1)。但是这样的空指针异常仍然会在运行时抛出来。

运行上面的代码,我们可以看到输出:

{"category":"金融财务类","gmtCreated":1500050426817,"gmtModified":1500050426817}
product name is null
falsenull cannot be cast to non-null type java.lang.String
kotlin.TypeCastException: null cannot be cast to non-null type java.lang.Stringat com.easy.kotlin.CallingJavaNullSafe.testCallingJavaNullSafe(CallingJavaNullSafe.kt:27)

我们没有设置name的值,在Java它就是null。我们在Kotlin代码中使用了这个name进行计算,我们可以看出:

        val eqName = name == "账务系统"println(eqName)

可以正确输出false。这表明Kotlin的判断字符串是否相等已经对null的情况作了判断处理,这样的代码如果在Java中调用 name.equals("账务系统") 就该抛空指针异常了。

但是当我们直接使用name这个值来调用name.substring(1)的时候,Kotlin编译器不会检查这个空异常,但是运行时还是要报错的:null cannot be cast to non-null type java.lang.String

如果我们不想看到这样的异常,而是当name是null的时候,安静的输出null,直接使用Kotlin中的空安全的调用 .?

name?.substring(1)

这样,运行的时候不会抛出异常,直接安静的返回null。

平台类型

平台类型不能在程序中显式表述,因此在语言中没有相应语法。 然而,编译器和 IDE 有时需要(在错误信息中、参数信息中等)显示他们,所以我们用一个助记符来表示他们:

  • T! : 表示 T 或者 T?

  • (Mutable) Collection<T>! : 表示 “可以可变或不可变、可空或不可空的 T 的 Java 集合”

  • Array<(out) T>! : 表示“可空或者不可空的 T(或 T 的子类型)的 Java 数组”

Kotlin与Java中的类型映射

Kotlin 特殊处理一部分 Java 类型。这样的类型不是“按原样”从 Java 加载,而是 映射 到相应的 Kotlin 类型。

映射只发生在编译期间,运行时表示保持不变。

Java 的原生类型映射到相应的 Kotlin 类型:

Java 类型Kotlin 类型
bytekotlin.Byte
shortkotlin.Short
intkotlin.Int
longkotlin.Long
charkotlin.Char
floatkotlin.Float
doublekotlin.Double
booleankotlin.Boolean

Java中的一些内置类型也会作相应的映射:

Java 类型Kotlin 类型
java.lang.Objectkotlin.Any!
java.lang.Cloneablekotlin.Cloneable!
java.lang.Comparablekotlin.Comparable!
java.lang.Enumkotlin.Enum!
java.lang.Annotationkotlin.Annotation!
java.lang.Deprecatedkotlin.Deprecated!
java.lang.CharSequencekotlin.CharSequence!
java.lang.Stringkotlin.String!
java.lang.Numberkotlin.Number!
java.lang.Throwablekotlin.Throwable!

Java 的装箱原始类型映射到对应的可空Kotlin 类型:

Java 类型Kotlin 类型
java.lang.Bytekotlin.Byte?
java.lang.Shortkotlin.Short?
java.lang.Integerkotlin.Int?
java.lang.Longkotlin.Long?
java.lang.Characterkotlin.Char?
java.lang.Floatkotlin.Float?
java.lang.Doublekotlin.Double?
java.lang.Booleankotlin.Boolean?

另外,用作类型参数的Java类型映射到Kotlin中的平台类型:
例如,List<java.lang.Integer> 在 Kotlin 中会成为 List<Int!>

集合类型在 Kotlin 中可以是只读的或可变的,因此 Java 集合类型作如下映射:
(下表中的所有 Kotlin 类型都在 kotlin.collections包中):

Java 类型Kotlin 只读类型Kotlin 可变类型加载的平台类型
Iterator<T>Iterator<T>MutableIterator<T>(Mutable)Iterator<T>!
Iterable<T>Iterable<T>MutableIterable<T>(Mutable)Iterable<T>!
Collection<T>Collection<T>MutableCollection<T>(Mutable)Collection<T>!
Set<T>Set<T>MutableSet<T>(Mutable)Set<T>!
List<T>List<T>MutableList<T>(Mutable)List<T>!
ListIterator<T>ListIterator<T>MutableListIterator<T>(Mutable)ListIterator<T>!
Map<K, V>Map<K, V>MutableMap<K, V>(Mutable)Map<K, V>!
Map.Entry<K, V>Map.Entry<K, V>MutableMap.MutableEntry<K,V>(Mutable)Map.(Mutable)Entry<K, V>!

Java 的数组映射:

Java 类型Kotlin 类型
int[]kotlin.IntArray!
String[]kotlin.Array<(out) String>!

Kotlin 中使用 Java 的泛型

Kotlin 的泛型与 Java 有点不同。当将 Java 类型导入 Kotlin 时,我们会执行一些转换:

Kotlin 的泛型Java 的泛型说明
Foo<out Bar!>!Foo<? extends Bar>Java 的通配符转换成类型投影
Foo<? super Bar>Foo<in Bar!>!同上
List<*>!ListJava的原始类型转换成星投影

和 Java 一样,Kotlin 在运行时不保留泛型,即对象不携带传递到他们构造器中的那些类型参数的实际类型。

ArrayList<Integer>()ArrayList<Character>() 是不能区分的。

Kotlin与Java 中的数组

与 Java 不同,Kotlin 中的数组是非型变的,即 Kotlin 不允许我们把一个 Array<String> 赋值给一个 Array<Any>

Java 平台上,持有原生数据类型的数组避免了装箱/拆箱操作的开销。
在Kotlin中,对于每种原生类型的数组都有一个特化的类(IntArrayDoubleArrayCharArray 等)来实现同样的功能。它们与 Array 类无关,并且会编译成 Java 原生类型数组以获得最佳性能。

Java 可变参数

Java 类有时声明一个具有可变数量参数(varargs)的方法来使用索引。

public class VarArgsDemo<T> {static VarArgsDemo vad = new VarArgsDemo();public static void main(String... agrs) {System.out.println(vad.append("a", "b", "c"));System.out.println(vad.append(1, 2, 3));System.out.println(vad.append(1, 2, "3"));}public String append(T... element) {StringBuilder result = new StringBuilder();for (T e : element) {result.append(e);}return result.toString();}
}

在Kotlin中,我们使用展开运算符 * 来传递这个varargs:

@RunWith(JUnit4::class)
class VarArgsDemoTest {@Test fun testVarArgsDemo() {val varArgsDemo = VarArgsDemo<Any?>()val array = arrayOf(0, 1, 2, 3)val result = varArgsDemo.append(*array)println(result)}
}

运行输出:0123

非受检异常

在 Kotlin 中,所有异常都是非受检的(Non-Checked Exceptions),这意味着编译器不会强迫你捕获其中的任何一个。而在Java中会要求我们捕获异常,例如下面的代码:

螢幕快照 2017-07-15 01.43.16.png

也就是说,我们需要写类似下面的try catch代码块:

        try {jsonUtils.parseObject("{}");} catch (Exception e) {e.printStackTrace();}

然而在Kotlin中情况就不是这样子了:当我们调用一个声明受检异常的 Java 方法时,Kotlin 不会强迫你做任何事情:

    @Test fun testNonCheckedExceptions() {val jsonUtils = JSONUtils()jsonUtils.parseObject("{}")}

但是,我们在运行的时候,还是会抛异常:

com.easy.kotlin.CallingJavaNullSafe > testNonCheckedExceptions FAILEDjava.lang.Exception at CallingJavaNullSafe.kt:34

Kotlin的不受检异常,这样也会导致运行时抛出异常。关于异常的处理,该处理的终归还是要处理的。

对象方法

Java中的java.lang.Object定义如下:

public class Object {private static native void registerNatives();static {registerNatives();}public final native Class<?> getClass();public native int hashCode();public boolean equals(Object obj) {return (this == obj);}protected native Object clone() throws CloneNotSupportedException;public String toString() {return getClass().getName() + "@" + Integer.toHexString(hashCode());}public final native void notify();public final native void notifyAll();public final native void wait(long timeout) throws InterruptedException;public final void wait(long timeout, int nanos) throws InterruptedException {...}public final void wait() throws InterruptedException {wait(0);}protected void finalize() throws Throwable { }

当 Java 类型导入到 Kotlin 中时,类型 java.lang.Object 的所有引用都成了 AnyAny只声明了 toString()hashCode()equals() 函数。怎样才能用到 java.lang.Object 的其他成员方法呢?下面我们来看下。

wait()/notify()

《Effective Java》 第 69 条中建议优先使用并发工具(concurrency utilities)而不是 wait()notify()。因此,类型 Any 的引用没有提供这两个方法。

如果我们真的需要调用它们的话,可以将其转换为 java.lang.Object来使用:

(foo as java.lang.Object).wait()

getClass()

要取得对象的 Java 类,我们可以在类引用上使用 java 扩展属性,它是Kotlin的反射类kotlin.reflect.KClass的扩展属性。

val fooClass = foo::class.java

上面的代码使用了自 Kotlin 1.1 起支持的绑定类引用。我们也可以使用 javaClass 扩展属性。

val fooClass = foo.javaClass

clone()

要覆盖 clone(),需要继承 kotlin.Cloneable


class Example : Cloneable {override fun clone(): Any { …… }
}

要谨慎地改写clone方法。

finalize()

要覆盖 finalize(),我们只需要声明它即可,不用再写 override关键字:

class C {protected fun finalize() {// 终止化逻辑}
}

访问静态成员

Java 类的静态成员会形成该类的“伴生对象”。我们可以直接显式访问其成员。例如:

一个带静态方法的Java类

public class JSONUtils {public static String toJsonString(Object o) {return JSON.toJSONString(o);}
}

我们在Kotlin代码可以直接这样调用:

@RunWith(JUnit4::class)
class JSONUtilsTest {@Test fun testJSONUtils() {val userService = UserServiceImpl()val user = userService.findByName("admin")Assert.assertTrue(user.name == "admin")val userJson = JSONUtils.toJsonString(user)println(userJson)Assert.assertTrue(userJson == "{\"name\":\"admin\",\"password\":\"admin\"}")}
}

上面我们提到过,如果是反过来调用,Java调用Kotlin中的object对象类中的函数,需要使用object的 对象名.INSTANCE 来调用函数。

Kotlin与Java 的反射

我们可以使用 instance::class.javaClassName::class.java 或者 instance.javaClass 通过 java.lang.Class 来进入 Java 的反射类java.lang.Class, 之后我们就可以使用Java中的反射的功能特性了。

代码示例:

@RunWith(JUnit4::class)
class RefectClassTest {@Test fun testGetterSetter() {val product = Product()val pClz = product::class.javaprintln(pClz.canonicalName)pClz.declaredFields.forEach { println(it) }pClz.declaredMethods.forEach {println(it.name);it.parameters.forEach { println(it) }}}
}

运行上面的代码输出:

com.easy.kotlin.Product
java.lang.Long com.easy.kotlin.Product.id
java.lang.String com.easy.kotlin.Product.name
java.lang.String com.easy.kotlin.Product.category
java.util.Date com.easy.kotlin.Product.gmtCreated
java.util.Date com.easy.kotlin.Product.gmtModified
getName
setName
java.lang.String arg0
getId
setId
java.lang.Long arg0
setCategory
java.lang.String arg0
getGmtCreated
setGmtCreated
java.util.Date arg0
getGmtModified
setGmtModified
java.util.Date arg0
getCategory

SAM 转换

我们在Kotlin中,要某个函数做某件事时,会传一个函数参数给它。 而在Java中,并不支持传送函数参数。通常Java的实现方式是将动作放在一个实现某接口的类中,然后将该类的一个实例传递给另一个方法。在大多数情况下,这些接口只有单个抽象方法(single abstract method),在Java中被称为SAM类型。

例如:Runnable接口:

@FunctionalInterface
public interface Runnable {public abstract void run();
}

在 Java 8中我们也通常称之为函数式接口。

Kotlin 支持 SAM 转换。Kotlin 的函数字面值可以被自动的转换成只有一个非默认方法的 Java 接口的实现,只要这个方法的参数类型能够与这个 Kotlin 函数的参数类型相匹配。

我们可以这样创建 SAM 接口的实例:

val runnable = Runnable { println("执行测试") } // Kotlin 调用Java的SAM接口方法

测试代码:

@RunWith(JUnit4::class)
class SAMFunctionalInterfaceTest {@Test fun testSAMFunctionalInterface() {val runnable = Runnable { println("执行测试") }val thread = Thread(runnable)thread.start()}
}

要注意的是,SAM 转换只适用于接口,而不适用于抽象类,即使这些抽象类也只有一个抽象方法。

还要注意,此功能只适用于 Java 互操作;因为 Kotlin 具有合适的函数类型,所以不需要将函数自动转换为 Kotlin 接口的实现。

Java使用了Kotlin的关键字

一些 Kotlin 关键字在 Java 中是有效标识符:inobjectis等等。

如果一个 Java 库使用了 Kotlin 关键字作为方法,我们可以通过反引号(`)字符转义它来调用该方法。例如我们有个Java类,其中有个is方法:

public class MathTools {public boolean is(Object o) {return true;}}

那么我们在Kotlin代码这样调用这个is方法:

@RunWith(JUnit4::class)
class MathToolsTest {@Test fun testISKeyWord(){val b = MathTools().`is`(1)}
}

Java 调用 Kotlin

Java 同样也可以调用 Kotlin 代码。但是要多用一些注解语法。

Java访问Kotlin属性

Kotlin 属性会编译成以下 Java 元素:

  • 一个 getter 方法,名称通过加前缀 get 算出;
  • 一个 setter 方法,名称通过加前缀 set 算出(只适用于 var 属性);
  • 一个与属性名称相同的私有字段。

例如,下面的Kotlin类:

class Department {var id: Long = -1Lvar name: String = "Dept"
}

会被编译成对应的 Java 代码:

public final class Department {private long id = -1L;@NotNullprivate String name = "Dept";public final long getId() {return this.id;}public final void setId(long var1) {this.id = var1;}@NotNullpublic final String getName() {return this.name;}public final void setName(@NotNull String var1) {Intrinsics.checkParameterIsNotNull(var1, "<set-?>");this.name = var1;}
}

我们可以看出,在Kotlin中的Long类型被编译成Java中的原生的long了。
我们在Java代码这样调用:

@RunWith(JUnit4.class)
public class JavaCallingKotlinCodeTest {@Testpublic void testProperty() {Department d = new Department();d.setId(1);d.setName("技术部");Assert.assertTrue(1 == d.getId());Assert.assertTrue("技术部".equals(d.getName()));}
}

另外,如果Kotlin的属性名以 is 开头,则使用不同的名称映射规则:

  • getter 的名称直接使用属性名称
  • setter 的名称是通过将 is 替换为 set 获得。

例如,对于属性 isOpen,其 getter 会称做 isOpen(),而其 setter 会称做 setOpen()

这一规则适用于任何类型的属性,并不仅限于 Boolean

代码示例:

Kotlin代码

class Department {var id: Long = -1Lvar name: String = "Dept"var isOpen:Boolean = truevar isBig:String = "Y"
}

Java调用Kotlin的测试代码:

    @Testpublic void testProperty() {Department d = new Department();d.setId(1);d.setName("技术部");d.setBig("Y");d.setOpen(true);Assert.assertTrue(1 == d.getId());Assert.assertTrue("技术部".equals(d.getName()));Assert.assertTrue("Y".equals(d.isBig()));Assert.assertTrue(d.isOpen());}

Java调用Kotlin的包级函数

package com.easy.kotlin 包内的 KotlinExample.kt 源文件中声明的所有的函数和属性,包括扩展函数,都将编译成一个名为 com.easy.kotlin.KotlinExampleKt 的 Java 类中的静态方法。

代码示例:

Kotlin的包级属性、函数代码:

package com.easy.kotlin/*** Created by jack on 2017/7/15.*/fun f1() {println("I am f1")
}fun f2() {println("I am f2")
}val p: String = "PPP"fun String.swap(index1: Int, index2: Int): String {val strArray = this.toCharArray()val tmp = strArray[index1]strArray[index1] = strArray[index2]strArray[index2] = tmpvar result = ""strArray.forEach { result += it }return result
}fun main(args: Array<String>) {println("abc".swap(0, 2))
}

编译成对应的Java的代码:

public final class KotlinExampleKt {@NotNullprivate static final String p = "PPP";public static final void f1() {String var0 = "I am f1";System.out.println(var0);}public static final void f2() {String var0 = "I am f2";System.out.println(var0);}@NotNullpublic static final String getP() {return p;}@NotNullpublic static final String swap(@NotNull String $receiver, int index1, int index2) {Intrinsics.checkParameterIsNotNull($receiver, "$receiver");char[] var10000 = $receiver.toCharArray();Intrinsics.checkExpressionValueIsNotNull(var10000, "(this as java.lang.String).toCharArray()");char[] strArray = var10000;char tmp = strArray[index1];strArray[index1] = strArray[index2];strArray[index2] = tmp;Object result = "";char[] $receiver$iv = strArray;for(int var7 = 0; var7 < $receiver$iv.length; ++var7) {char element$iv = $receiver$iv[var7];result = result + element$iv;}return result;}public static final void main(@NotNull String[] args) {Intrinsics.checkParameterIsNotNull(args, "args");String var1 = swap("abc", 0, 2);System.out.println(var1);}
}

我们可以看到,Kotlin中的扩展函数

fun String.swap(index1: Int, index2: Int): String

被编译成

public static final String swap(@NotNull String $receiver, int index1, int index2)

Kotlin中的String. 接收者被当做Java方法中的第一个参数传入。

Java调用Kotlin包级属性、函数的测试代码:

    @Testpublic void testPackageFun() {KotlinExampleKt.f1();KotlinExampleKt.f2();System.out.println(KotlinExampleKt.getP());KotlinExampleKt.swap("abc",0,1);}

运行输出:

I am f1
I am f2
PPP
bac

另外,要注意的这里生成的类KotlinExampleKt,我们不能使用new来创建实例对象:

KotlinExampleKt example = new KotlinExampleKt();// 报错

报如下错误:

error: cannot find symbolKotlinExampleKt example = new KotlinExampleKt();^symbol:   constructor KotlinExampleKt()location: class KotlinExampleKt
1 error

在编程中,我们推荐使用Kotlin默认的命名生成规则。如果确实有特殊场景需要自定义Kotlin包级函数对应的生成Java类的名字,我们可以使用 @JvmName 注解修改生成的 Java 类的类名:

@file:JvmName("MyKotlinExample")package com.easy.kotlin/*** Created by jack on 2017/7/15.*/fun f3() {println("I am f3")
}fun f4() {println("I am f4")
}val p2: String = "PPP"

测试代码:

MyKotlinExample.f3();
MyKotlinExample.f4();

实例字段

我们使用 @JvmField 注解对Kotlin中的属性字段标注,表示这是一个实例字段(Instance Fields),Kotlin编译器在处理的时候,将不会给这个字段生成getters/setters方法。

class Department {var id: Long = -1Lvar name: String = "Dept"var isOpen: Boolean = truevar isBig: String = "Y"@JvmField var NO = 0
}

映射成Java的代码就是:

public final class Department {private long id = -1L;@NotNullprivate String name = "Dept";private boolean isOpen = true;@NotNullprivate String isBig = "Y";@JvmFieldpublic int NO;public final long getId() {return this.id;}public final void setId(long var1) {this.id = var1;}@NotNullpublic final String getName() {return this.name;}public final void setName(@NotNull String var1) {Intrinsics.checkParameterIsNotNull(var1, "<set-?>");this.name = var1;}public final boolean isOpen() {return this.isOpen;}public final void setOpen(boolean var1) {this.isOpen = var1;}@NotNullpublic final String isBig() {return this.isBig;}public final void setBig(@NotNull String var1) {Intrinsics.checkParameterIsNotNull(var1, "<set-?>");this.isBig = var1;}
}

我们在Java中调用的时候,就直接使用这个属性实例字段NO

System.out.println(d.NO = 10);

静态字段

Kotlin中在命名对象或伴生对象中声明的 属性:

class Department {...companion object {var innerID = "X001"@JvmFieldvar innerName = "DEP"}
}

innerID、innerName这两个字段的区别在于可见性上:

   @NotNullprivate static String innerID = "X001";@JvmField@NotNullpublic static String innerName = "DEP";

这个私有的innerID通过Companion对象来封装,提供出public的getInnerID() 、setInnerID来访问:

   public static final class Companion {@NotNullpublic final String getInnerID() {return Department.innerID;}public final void setInnerID(@NotNull String var1) {Intrinsics.checkParameterIsNotNull(var1, "<set-?>");Department.innerID = var1;}private Companion() {}// $FF: synthetic methodpublic Companion(DefaultConstructorMarker $constructor_marker) {this();}}

我们在Java访问的innerID时候,是通过Companion来访问:

Department.Companion.getInnerID()

而我们使用@JvmField注解的字段innerName ,Kotlin编译器会把它的访问权限设置是public的,这样我们就可以这样访问这个属性字段了:

Department.innerName

静态方法

Kotlin 中,我还可以将命名对象或伴生对象中定义的函数标注为 @JvmStatic,这样编译器既会在相应对象的类中生成静态方法,也会在对象自身中生成实例方法。

跟静态属性类似的,我们看下面的代码示例:

class Department {...companion object {var innerID = "X001"@JvmFieldvar innerName = "DEP"fun getObjectName() = "ONAME"@JvmStaticfun getObjectID() = "OID"}
}

编译器编译之后,反编译成的对应的Java代码:

public final class Department {...@JvmStatic@NotNullpublic static final String getObjectID() {return Companion.getObjectID();}public static final class Companion {...@NotNullpublic final String getObjectName() {return "ONAME";}@JvmStatic@NotNullpublic final String getObjectID() {return "OID";}...}
}

在Java中调用的代码如下:

        Department.Companion.getObjectID(); // OKDepartment.Companion.getObjectName(); // OK, 唯一的工作方式Department.getObjectID(); // ALSO OKDepartment.getObjectName(); // ERROR

这些注解语法是编译器为了更加方便Java调用Kotlin代码提供的一些简便技巧。这样可使得Java中调用Kotlin代码更加自然优雅些。

可见性

Kotlin 的可见性与Java的可见性的映射关系如下表所示:

Kotlin中的声明Java中的声明
privateprivate
protectedprotected
internalpublic
publicpublic

例如下面的Kotlin代码:

class ProgrammingBook {private var isbn: String = "978-7-111-44250-9"protected var author: String = "Cay"public var name: String = "Core Java"internal var pages: Int = 300private fun findISBN(): String = "978-7-111-44250-9"protected fun findAuthor(): String = "Cay"public fun findName(): String = "Core Java"internal fun findPages(): Int = 300
}

对应的Java的代码是:

public final class ProgrammingBook {private String isbn = "978-7-111-44250-9";@NotNullprivate String author = "Cay";@NotNullprivate String name = "Core Java";private int pages = 300;@NotNullprotected final String getAuthor() {return this.author;}protected final void setAuthor(@NotNull String var1) {Intrinsics.checkParameterIsNotNull(var1, "<set-?>");this.author = var1;}@NotNullpublic final String getName() {return this.name;}public final void setName(@NotNull String var1) {Intrinsics.checkParameterIsNotNull(var1, "<set-?>");this.name = var1;}public final int getPages$production_sources_for_module_chapter10_interoperability_main() {return this.pages;}public final void setPages$production_sources_for_module_chapter10_interoperability_main(int var1) {this.pages = var1;}private final String findISBN() {return "978-7-111-44250-9";}@NotNullprotected final String findAuthor() {return "Cay";}@NotNullpublic final String findName() {return "Core Java";}public final int findPages$production_sources_for_module_chapter10_interoperability_main() {return 300;}
}

我们可以看到Kotlin中的可见性跟Java中的基本相同。

生成默认参数值函数的重载

我们在Kotlin中写一个有默认参数值的 Kotlin 方法,它会对每一个有默认值的参数都生成一个重载函数。这样的Kotlin函数,在 Java 中调用的话,只会有一个所有参数都存在的完整参数签名方法可见。如果我们希望Java像Kotlin中一样可以调用多个重载,可以使用@JvmOverloads注解。

下面我们来通过一个实例对比两者的区别:

这是一段Kotlin代码:

class OverridesFunWithDefaultParams {fun f1(a: Int = 0, b: String = "B") {}@JvmOverloads fun f2(a: Int = 0, b: String = "B") {}
}

函数f1 和 f2 都带有默认参数。测试代码如下:

    @Testpublic void testOverridesFunWithDefaultParams() {OverridesFunWithDefaultParams ofdp = new OverridesFunWithDefaultParams();ofdp.f1(1, "a");ofdp.f2();ofdp.f2(2);ofdp.f2(2, "b");}

这就是@JvmOverloads注解的作用,编译器会处理这个注解所标注的函数,并为之生成额外的重载函数给Java调用。

检查Kotlin中异常

如上所述,Kotlin 没有受检异常。即像下面像这样的 Kotlin 函数:

class CheckKotlinException {fun thisIsAFunWithException() {throw Exception("I am an exception in kotlin")}
}

在Java中调用,编译器是不会检查这个异常的:

    @Testpublic void testCheckKotlinException() {CheckKotlinException cke = new CheckKotlinException();cke.thisIsAFunWithException();// Java编译器不检查这个Kotlin中的异常}

当然,在运行时,这个异常还是会抛出来。然后,如果我们想要在 Java 中调用它并捕捉这个异常,我们可以给Kotlin中的函数加上注解@Throws(Exception::class), 就像下面这样:

    @Throws(Exception::class)fun thisIsAnotherFunWithException() {throw Exception("I am Another exception in kotlin")}

然后,我们在Java中调用的时候,Java编译器就会检查这个异常:

螢幕快照 2017-07-15 21.49.17.png

最后,我们的代码就需要捕获该异常并处理它。

完整的示例代码如下:

package com.easy.kotlin/*** Created by jack on 2017/7/15.*/
class CheckKotlinException {fun thisIsAFunWithException() {throw Exception("I am an exception in kotlin")}@Throws(Exception::class)fun thisIsAnotherFunWithException() {throw Exception("I am Another exception in kotlin")}
}

测试代码:

package com.easy.kotlin;import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;/*** Created by jack on 2017/7/15.*/
@RunWith(JUnit4.class)
public class CheckKotlinExceptionTest {@Testpublic void testCheckKotlinException() {CheckKotlinException cke = new CheckKotlinException();cke.thisIsAFunWithException();// Java编译器不检查这个Kotlin中的异常// Kotlin中显示声明了异常,Java编译器会检查这个异常// cke.thisIsAnotherFunWithException();try {cke.thisIsAnotherFunWithException();} catch (Exception e) {e.printStackTrace();}}
}

Nothing 类型

在Kotlin中Nothing类型是一个特殊的类型,它在 Java 中没有的对应的类型。在使用 Nothing 参数的地方会生成一个原始类型。

例如下面的Kotlin代码:

fun emptyList(): List<Nothing> = listOf()

对应到Java代码中是:

   @NotNullpublic final List emptyList() {return CollectionsKt.emptyList();}

Kotlin中的List<Nothing> 映射为原生类型List

Kotlin与Java对比

在前面的内容里,我们已经看到了Java与Kotlin的互操作的基本方式。为了更好的认识Java与Kotlin这两门语言,我们在这里给出一些基本功能,同时使用Java与Kotlin来实现的代码实例。通过横向对比,从中我们可以看出它们的异同。

(此处可整理成表格形式)

打印日志

  • Java
System.out.print("Java");
System.out.println("Java");
  • Kotlin
print("Kotlin")
println("Kotlin")

其实,Kotlin中的println函数是一个内联函数,它其实就是通过封装java.lang.System类的System.out.println来实现的。

@kotlin.internal.InlineOnly
public inline fun print(message: Any?) {System.out.print(message)
}

常量与变量

  • Java
String name = "KotlinVSJava";
final String name = "KotlinVSJava";
  • Kotlin
var name = "KotlinVSJava"
val name = "KotlinVSJava"

null声明

  • Java
String otherName;
otherName = null;
  • Kotlin
var otherName : String?
otherName = null

空判断

  • Java
if (text != null) {int length = text.length();
}
  • Kotlin
text?.let {val length = text.length
}
// 或者
val length = text?.length

在Kotlin中,我们只使用一个问号安全调用符号就省去了Java中烦人的if - null 判断。

字符串拼接

  • Java
String firstName = "Jack";
String lastName = "Chen";
String message = "My name is: " + firstName + " " + lastName;
  • Kotlin
val firstName = "Jack"
val lastName = "Chen"
val message = "My name is: $firstName $lastName"

Kotlin中使用$${}(花括号里面是表达式的时候)占位符来实现字符串的拼接,这个比在Java中每次使用加号来拼接要方便许多。

换行

  • Java
String text = "First Line\n" +"Second Line\n" +"Third Line";
  • Kotlin
val text = """|First Line|Second Line|Third Line""".trimMargin()

三元表达式

  • Java
String text = x > 5 ? "x > 5" : "x <= 5";
  • Kotlin
val text = if (x > 5)"x > 5"else "x <= 5"

操作符

  • java
final int andResult  = a & b;
final int orResult   = a | b;
final int xorResult  = a ^ b;
final int rightShift = a >> 2;
final int leftShift  = a << 2;
  • Kotlin
val andResult  = a and b
val orResult   = a or b
val xorResult  = a xor b
val rightShift = a shr 2
val leftShift  = a shl 2

类型判断和转换(显式)

  • Java
if (object instanceof Car) {
}
Car car = (Car) object;
  • Kotlin
if (object is Car) {
}
var car = object as Car

类型判断和转换 (隐式)

  • Java
if (object instanceof Car) {Car car = (Car) object;
}
  • Kotlin
if (object is Car) {var car = object // Kotlin智能转换
}

Kotlin的类型系统具备一定的类型推断能力,这样也省去了不少在Java中类型转换的样板式代码。

Range区间

  • Java
if (score >= 0 && score <= 300) { }
  • Kotlin
if (score in 0..300) { }

更灵活的case语句

  • Java
    public String getGrade(int score) {String grade;switch (score) {case 10:case 9:grade = "A";break;case 8:case 7:case 6:grade = "B";break;case 5:case 4:grade = "C";break;case 3:case 2:case 1:grade = "D";break;default:grade = "E";}return grade;}
  • Kotlin
fun getGrade(score: Int): String {var grade = when (score) {9, 10 -> "A"in 6..8 -> "B"4, 5 -> "C"in 1..3 -> "D"else -> "E"}return grade
}

for循环

  • Java
for (int i = 1; i <= 10 ; i++) { }for (int i = 1; i < 10 ; i++) { }for (int i = 10; i >= 0 ; i--) { }for (int i = 1; i <= 10 ; i+=2) { }for (int i = 10; i >= 0 ; i-=2) { }for (String item : collection) { }for (Map.Entry<String, String> entry: map.entrySet()) { }
  • Kotlin
for (i in 1..10) { }for (i in 1 until 10) { }for (i in 10 downTo 0) { }for (i in 1..10 step 2) { }for (i in 10 downTo 1 step 2) { }for (item in collection) { }for ((key, value) in map) { }

更方便的集合操作

  • Java
final List<Integer> listOfNumber = Arrays.asList(1, 2, 3, 4);
final Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "Jack");
map.put(2, "Ali");
map.put(3, "Mindorks");
  • Kotlin
val listOfNumber = listOf(1, 2, 3, 4)
val map = mapOf(1 to "Jack", 2 to "Ali", 3 to "Mindorks")

遍历

  • Java
// Java 7 
for (Car car : cars) {System.out.println(car.speed);
}// Java 8+
cars.forEach(car -> System.out.println(car.speed));// Java 7 
for (Car car : cars) {if (car.speed > 100) {System.out.println(car.speed);}
}// Java 8+
cars.stream().filter(car -> car.speed > 100).forEach(car -> System.out.println(car.speed));
  • Kotlin
cars.forEach {println(it.speed)
}cars.filter { it.speed > 100 }.forEach { println(it.speed)}

方法(函数)定义

  • Java
void doSomething() {// 实现
}void doSomething(int... numbers) {// 实现
}
  • Kotlin
fun doSomething() {// 实现
}fun doSomething(vararg numbers: Int) {// 实现
}

带返回值的方法(函数)

  • Java
int getScore() {// logic herereturn score;
}
  • Kotlin
fun getScore(): Int {// logic herereturn score
}// 单表达式函数
fun getScore(): Int = score

另外,Kotlin中的函数是可以直接传入函数参数,同时可以返回一个函数类型的。

constructor 构造器

  • Java
public class Utils {private Utils() { // 外部无法来调用实例化}public static int getScore(int value) {return 2 * value;}}
  • Kotlin
class Utils private constructor() {companion object {fun getScore(value: Int): Int {return 2 * value}}
}// 或者直接声明一个object对象
object Utils {fun getScore(value: Int): Int {return 2 * value}}

JavaBean与Kotlin数据类

这段Kotlin中的数据类的代码:

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

对应下面这段Java实体类的代码:

  • Java
public final class Developer {@NotNullprivate final String name;private final int age;@NotNullpublic final String getName() {return this.name;}public final int getAge() {return this.age;}public Developer(@NotNull String name, int age) {Intrinsics.checkParameterIsNotNull(name, "name");super();this.name = name;this.age = age;}@NotNullpublic final String component1() {return this.name;}public final int component2() {return this.age;}@NotNullpublic final Developer copy(@NotNull String name, int age) {Intrinsics.checkParameterIsNotNull(name, "name");return new Developer(name, age);}// $FF: synthetic method// $FF: bridge method@NotNullpublic static Developer copy$default(Developer var0, String var1, int var2, int var3, Object var4) {if((var3 & 1) != 0) {var1 = var0.name;}if((var3 & 2) != 0) {var2 = var0.age;}return var0.copy(var1, var2);}public String toString() {return "Developer(name=" + this.name + ", age=" + this.age + ")";}public int hashCode() {return (this.name != null?this.name.hashCode():0) * 31 + this.age;}public boolean equals(Object var1) {if(this != var1) {if(var1 instanceof Developer) {Developer var2 = (Developer)var1;if(Intrinsics.areEqual(this.name, var2.name) && this.age == var2.age) {return true;}}return false;} else {return true;}}
}

本章小结

本章我们一起学习了Kotlin与Java的互操作,同时我们用一些简单的示例对比了它们的异同。在这之中,我们能感受到Kotlin的简洁、优雅。 我们可以用更少的代码来实现更多的功能。 另外,在IDEA中,我们可以直接使用Kotlin插件来直接进行Java代码与Kotlin代码之间的转换(虽然,有些情况下需要我们手工再去稍作改动)。

Kotlin的定位本身之一就是官网首页重点强调的:100% interoperable with Java™。它并不是scala那样另起炉灶, 将类库(例如,集合类)都自己实现了一遍。kotlin是对现有Java的增强,通过扩展方法给java提供了很多诸如fp之类的特性, 但同时始终保持对java的兼容。

而在Java生态领域最为人知的Spring框架,在最新的Spring 5中对Kotlin也作了支持(参看:https://spring.io/blog/2017/01/04/introducing-kotlin-support-in-spring-framework-5-0) 。 当前,作为Spring大家族中最引人注目的非Spring Boot莫属了。我们即将在下一章中介绍Kotlin集成Spring Boot来开发服务端Web项目。

本章示例代码:

https://github.com/EasyKotlin/chapter10_interoperability


Kotlin开发者社区

专注分享 Java、 Kotlin、Spring/Spring Boot、MySQL、redis、neo4j、NoSQL、Android、JavaScript、React、Node、函数式编程、编程思想、"高可用,高性能,高实时"大型分布式系统架构设计主题。

High availability, high performance, high real-time large-scale distributed system architecture design

分布式框架:Zookeeper、分布式中间件框架等
分布式存储:GridFS、FastDFS、TFS、MemCache、redis等
分布式数据库:Cobar、tddl、Amoeba、Mycat
云计算、大数据、AI算法
虚拟化、云原生技术
分布式计算框架:MapReduce、Hadoop、Storm、Flink等
分布式通信机制:Dubbo、RPC调用、共享远程数据、消息队列等
消息队列MQ:Kafka、MetaQ,RocketMQ
怎样打造高可用系统:基于硬件、软件中间件、系统架构等一些典型方案的实现:HAProxy、基于Corosync+Pacemaker的高可用集群套件中间件系统
Mycat架构分布式演进
大数据Join背后的难题:数据、网络、内存和计算能力的矛盾和调和
Java分布式系统中的高性能难题:AIO,NIO,Netty还是自己开发框架?
高性能事件派发机制:线程池模型、Disruptor模型等等。。。

合抱之木,生于毫末;九层之台,起于垒土;千里之行,始于足下。不积跬步,无以至千里;不积小流,无以成江河。

Kotlin 简介

Kotlin是一门非研究性的语言,它是一门非常务实的工业级编程语言,它的使命就是帮助程序员们解决实际工程实践中的问题。使用Kotlin 让 Java程序员们的生活变得更好,Java中的那些空指针错误,浪费时间的冗长的样板代码,啰嗦的语法限制等等,在Kotlin中统统消失。Kotlin 简单务实,语法简洁而强大,安全且表达力强,极富生产力。

Java诞生于1995年,至今已有23年历史。当前最新版本是 Java 9。在 JVM 生态不断发展繁荣的过程中,也诞生了Scala、Groovy、Clojure 等兄弟语言。

Kotlin 也正是 JVM 家族中的优秀一员。Kotlin是一种现代语言(版本1.0于2016年2月发布)。它最初的目的是像Scala那样,优化Java语言的缺陷,提供更加简单实用的编程语言特性,并且解决了性能上的问题,比如编译时间。 JetBrains在这些方面做得非常出色。

Kotlin语言的特性

用 Java 开发多年以后,能够尝试一些新的东西真是太棒了。如果您是 Java 开发人员,使用 Kotlin 将会非常自然流畅。如果你是一个Swift开发者,你将会感到似曾相识,比如可空性(Nullability)。 Kotlin语言的特性有:

1.简洁

大幅减少样板代码量。

2.与Java的100%互操作性

Kotlin可以直接与Java类交互,反之亦然。这个特性使得我们可以直接重用我们的代码库,并将其迁移到 Kotlin中。由于Java的互操作性几乎无处不在。我们可以直接访问平台API以及现有的代码库,同时仍然享受和使用 Kotlin 的所有强大的现代语言功能。

3.扩展函数

Kotlin 类似于 C# 和 Gosu, 它提供了为现有类提供新功能扩展的能力,而不必从该类继承或使用任何类型的设计模式 (如装饰器模式)。

4.函数式编程

Kotlin 语言一等支持函数式编程,就像Scala一样。具备高阶函数、Lambda 表达式等函数式基本特性。

5.默认和命名参数

在Kotlin中,您可以为函数中的参数设置一个默认值,并给每个参数一个名称。这有助于编写易读的代码。

6.强大的开发工具支持

而由于是JetBrains出品,我们拥有很棒的IDE支持。虽然Java到Kotlin的自动转换并不是100% OK 的,但它确实是一个非常好的工具。使用 IDEA 的工具转换Java代码为 Kotlin 代码时,可以轻松地重用60%-70%的结果代码,而且修改成本很小。

Kotlin 除了简洁强大的语法特性外,还有实用性非常强的API以及围绕它构建的生态系统。例如:集合类 API、IO 扩展类、反射API 等。同时 Kotlin 社区也提供了丰富的文档和大量的学习资料,还有在线REPL。

A modern programming language that makes developers happier. Open source forever

图来自《Kotlin从入门到进阶实战》 (陈光剑,清华大学出版社)

图来自《Kotlin从入门到进阶实战》 (陈光剑,清华大学出版社)

https://kotlinlang.org/

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. jmeter压测oracle

    下载oracle驱动 <dependency><groupId>com.oracle.jdbc</groupId><artifactId>ojdbc6</artifactId><version>${ojdbc.version}</version> </dependency> 拷贝驱动 把驱动放到jmeter的lib目录下 添加 设置jdbc连接 添加jdbc…...

    2024/4/22 14:01:26
  2. CSS样式更改——用户界面和指针类型

    ###前言 上篇文章主要讲述了CSS样式更改中的多列、元素是否可见、图片透明度基础知识&#xff0c;这篇文章我们来介绍下CSS样式更改中用户界面和指针类型基础用法。 ####1.用户界面 UserGui 1).重设元素大小 resize div { resize:both } none 不调整 both …...

    2024/4/26 15:26:53
  3. time-formater 时间格式化插件

    time-formater 不是 time-format[t]er English 在javascript中显示日期。 使用方法 下载 npm i -S time-formaterlet rawDate time().format(YYYY-MM-DD HH:mm:ss) // 当前时间console.log(rawDate) // 2020-12-28 15:19:34解析 当前时间 let now time() 如果参数为空则获…...

    2024/5/3 16:38:24
  4. OceanBase架构初探

    本文源自&#xff1a;https://blog.csdn.net/jiankunking/article/details/84020030 1、设计思路 OceanBase的目标是支持数百TB的数据量以及数十万TPS、数百万QPS的访问量&#xff0c;无论是数据量还是访问量&#xff0c;即使采用非常昂贵的小型机甚至是大型机&#xff0c;单…...

    2024/4/7 10:37:57
  5. 风控-数据分析

    数据总体了解&#xff1a; 读取数据集并了解数据集大小&#xff0c;原始特征维度&#xff1b; 通过info熟悉数据类型&#xff1b; 粗略查看数据集中各特征基本统计量&#xff1b; 缺失值和唯一值&#xff1a; 查看数据缺失值情况 查看唯一值特征情况 深入数据-查看数据类…...

    2024/4/23 4:56:36
  6. 如何求解大多数动态规划(DP)问题

    From-good-to-great.-How-to-approach-most-of-DP-problems. 解决思路&#xff1a; 查找递归关系递归&#xff08;自上而下&#xff09;递归记忆数组&#xff08;自上而下&#xff09;迭代记忆数组&#xff08;自下而上&#xff09;迭代N个变量&#xff08;自下而上&#xff…...

    2024/4/25 1:34:40
  7. 独立站Shopify VS 亚马逊FBA !跨境电商创业哪个平台更适合个人创业?

    做跨境电商您选择好做那个平台了吗&#xff1f;不确定如何选择&#xff1f;也许您一直在评估不同的平台&#xff0c;但没有确定下来&#xff01;也许您已经将其范围缩小到这两个选项&#xff0c;或者您仍在寻找更多选择。 无论哪种方式&#xff0c;让我们来看一下为什么Shopif…...

    2024/4/7 10:37:59
  8. 数据库:MySQL查询一个表的所有字段

    SELECTCOLUMN_NAME FROMINFORMATION_SCHEMA. COLUMNS WHEREtable_name 查询的数据表名 AND table_schema 数据库名...

    2024/4/22 17:31:28
  9. LeetCode 155. 最小栈

    问题描述&#xff1a; 代码&#xff1a; class MinStack { public:stack<int> data;stack<int> min;MinStack() {}void push(int x) {data.push(x);if (min.empty() || min.top() > x) //总是把最小的元素压到min栈里面{min.push(x);}else{min.push(min.top())…...

    2024/4/22 23:52:33
  10. 获取exe路径

    #include <string> #include <iostream> #include <Windows.h>using namespace std;string GetExePath(void) {char szFilePath[MAX_PATH 1] { 0 };GetModuleFileNameA(NULL, szFilePath, MAX_PATH);(strrchr(szFilePath, \\))[0] 0; // 删除文件名&#…...

    2024/4/7 11:24:08
  11. servlet+mysql+filter+jsp项目:破烂音乐

    上个学期完成了Java web课程学习后&#xff0c;按照课程要求&#xff0c;要做一个servletmysqlfilterjsp的项目&#xff0c;由于时间有限&#xff0c;在上网逛了一圈后就在52论坛找到一个坛友分享的音乐播放器项目&#xff0c;这里非常感谢&#xff1a; https://www.52pojie.cn…...

    2024/4/7 11:24:07
  12. Ubuntu18.04更换国内源

    Ubuntu18.04更换国内源 这里讲解如何ubuntu系统如何更换阿里云源&#xff0c;作为科研的起步&#xff0c;跟着我&#xff0c;一步一步进入到机器学习的世界中吧&#xff01; 1.打开源文件 sudo vi /etc/apt/sources.list dd(长按) i 鼠标右键-粘贴你复制的源 esc :wq2.将原有…...

    2024/4/7 11:24:06
  13. 知道车架号,vin想查询车辆维修和出险记录,以上 JavaScript 代码可以通过 HTML 代码来调用

    function validateForm() {var x document.forms["myForm"]["fname"].value;if (x null || x "") {alert("需要输入名字。");return false;} } 知道车架号&#xff0c;vin想查询车辆维修和出险记录。 现在使用手机微信&#xff0…...

    2024/4/12 0:00:07
  14. 【LeetCode每日一题】47. 全排列 II

    【LeetCode每日一题】47. 全排列 II 47. 全排列 II 题目来源link 算法思想&#xff1a;回溯法&#xff0c;递归&#xff1b; 给定数组{1,1,2} 图片链接link PS&#xff1a;关键在于条件判断&#xff0c;用于回溯中剪枝&#xff0c;去重 // 这里理解used[i - 1]非常重要 …...

    2024/5/4 7:59:18
  15. 《Kotlin极简教程》第1章 Kotlin简介

    第1章 Kotlin简介 1.1 kotlin简史 1.1.1 Kotlin概述 科特林岛&#xff08;Котлин&#xff09;是一座俄罗斯的岛屿&#xff0c;位于圣彼得堡以西约30公里处&#xff0c;形状狭长&#xff0c;东西长度约14公里&#xff0c;南北宽度约2公里&#xff0c;面积有16平方公里&a…...

    2024/4/23 2:24:36
  16. 《Linux性能优化实战》笔记(八)—— 内存是怎么工作的

    一、 内存映射 我们通常所说的内存容量&#xff0c;指的是物理内存。物理内存也称为主存&#xff0c;大多数计算机用的主存都是动态随机访问内存&#xff08;DRAM&#xff09;。只有内核才可以直接访问物理内存。那么&#xff0c;进程要访问内存时&#xff0c;该怎么办呢&…...

    2024/4/20 19:16:37
  17. 5G网络的远程手术示教演示

    5G网络的远程手术示教演示 远程手术示教&#xff0c;大家并不陌生&#xff0c;在很多医院得到了普遍的应用。可是同时也受到带宽和信号的限制&#xff0c;无法真正达到身临其境的目的。而现在5G网络的出现&#xff0c;手术示教系统才能真正能够发挥其作用。 下面&#xff0c;…...

    2024/4/7 11:24:01
  18. 展讯8541E平台NFC PM1810驱动调试

    一&#xff0c;非接芯片PM1810介绍 1. PM1810管脚排列图&#xff1a; 2. PM1810部分接线图&#xff1a; 3. PM1810发射、接收电路&#xff1a; 二&#xff0c;驱动代码部分的修改&#xff1a; kernel4.4/arch/arm64/boot/dts/sprd/sl8541e-1h10-native.dts &spi0 {/*use…...

    2024/4/27 22:32:38
  19. 第3章 Kotlin语言基础

    第3章 Kotlin语言基础 掌握基础&#xff0c;持续练习 学习任何东西&#xff0c;都是一个由表及里的过程。学习一门编程语言也一样。对于一门编程语言来说&#xff0c;“表” 就是基本词汇&#xff08;关键字、标识符等&#xff09;、句子&#xff08;表达式&#xff09;和语法。…...

    2024/4/24 4:18:26
  20. 【神奇的CV】计算机视觉不同方向的demo展示

    一、行人ReID&#xff08;跨境追踪&#xff09;、行人跟踪方向 跨境追踪&#xff08;Person Re-Identification&#xff0c;简称 ReID&#xff09;技术&#xff0c;又称为行人重识别&#xff0c;是计算机视觉方向的热点课题&#xff0c;主要解决跨摄像头、跨场景下的行人识别与…...

    2024/4/7 11:23:58

最新文章

  1. Java新手必看:快速上手FileOutPutStream类

    哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…...

    2024/5/6 23:38:57
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/5/6 9:38:23
  3. jQuery(一)

    文章目录 1. 基本介绍2.原理示意图3.快速入门1.下载jQuery2.创建文件夹&#xff0c;放入jQuery3.引入jQuery4.代码实例 4.jQuery对象与DOM对象转换1.基本介绍2.dom对象转换JQuery对象3.JQuery对象转换dom对象4.jQuery对象获取数据获取value使用val&#xff08;&#xff09;获取…...

    2024/5/4 22:17:11
  4. WIFI驱动移植实验:WIFI从路由器动态获取IP地址与联网

    一. 简介 前面两篇文章&#xff0c;一篇文章实现了WIFI联网前要做的工作&#xff0c;另一篇文章配置了WIFI配置文件&#xff0c;进行了WIFI热点的连接。文章如下&#xff1a; WIFI驱动移植实验&#xff1a;WIFI 联网前的工作-CSDN博客 WIFI驱动移植实验&#xff1a;连接WIF…...

    2024/5/4 17:27:10
  5. 416. 分割等和子集问题(动态规划)

    题目 题解 class Solution:def canPartition(self, nums: List[int]) -> bool:# badcaseif not nums:return True# 不能被2整除if sum(nums) % 2 ! 0:return False# 状态定义&#xff1a;dp[i][j]表示当背包容量为j&#xff0c;用前i个物品是否正好可以将背包填满&#xff…...

    2024/5/6 18:23:10
  6. 【Java】ExcelWriter自适应宽度工具类(支持中文)

    工具类 import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet;/*** Excel工具类** author xiaoming* date 2023/11/17 10:40*/ public class ExcelUti…...

    2024/5/6 18:40:38
  7. Spring cloud负载均衡@LoadBalanced LoadBalancerClient

    LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon&#xff0c;直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件&#xff0c;我们讨论Spring负载均衡以Spring Cloud2020之后版本为主&#xff0c;学习Spring Cloud LoadBalance&#xff0c;暂不讨论Ribbon…...

    2024/5/6 23:37:19
  8. TSINGSEE青犀AI智能分析+视频监控工业园区周界安全防范方案

    一、背景需求分析 在工业产业园、化工园或生产制造园区中&#xff0c;周界防范意义重大&#xff0c;对园区的安全起到重要的作用。常规的安防方式是采用人员巡查&#xff0c;人力投入成本大而且效率低。周界一旦被破坏或入侵&#xff0c;会影响园区人员和资产安全&#xff0c;…...

    2024/5/6 7:24:07
  9. VB.net WebBrowser网页元素抓取分析方法

    在用WebBrowser编程实现网页操作自动化时&#xff0c;常要分析网页Html&#xff0c;例如网页在加载数据时&#xff0c;常会显示“系统处理中&#xff0c;请稍候..”&#xff0c;我们需要在数据加载完成后才能继续下一步操作&#xff0c;如何抓取这个信息的网页html元素变化&…...

    2024/5/5 15:25:47
  10. 【Objective-C】Objective-C汇总

    方法定义 参考&#xff1a;https://www.yiibai.com/objective_c/objective_c_functions.html Objective-C编程语言中方法定义的一般形式如下 - (return_type) method_name:( argumentType1 )argumentName1 joiningArgument2:( argumentType2 )argumentName2 ... joiningArgu…...

    2024/5/6 6:01:13
  11. 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】

    &#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】&#x1f30f;题目描述&#x1f30f;输入格…...

    2024/5/6 7:24:06
  12. 【ES6.0】- 扩展运算符(...)

    【ES6.0】- 扩展运算符... 文章目录 【ES6.0】- 扩展运算符...一、概述二、拷贝数组对象三、合并操作四、参数传递五、数组去重六、字符串转字符数组七、NodeList转数组八、解构变量九、打印日志十、总结 一、概述 **扩展运算符(...)**允许一个表达式在期望多个参数&#xff0…...

    2024/5/6 1:08:53
  13. 摩根看好的前智能硬件头部品牌双11交易数据极度异常!——是模式创新还是饮鸩止渴?

    文 | 螳螂观察 作者 | 李燃 双11狂欢已落下帷幕&#xff0c;各大品牌纷纷晒出优异的成绩单&#xff0c;摩根士丹利投资的智能硬件头部品牌凯迪仕也不例外。然而有爆料称&#xff0c;在自媒体平台发布霸榜各大榜单喜讯的凯迪仕智能锁&#xff0c;多个平台数据都表现出极度异常…...

    2024/5/6 20:04:22
  14. Go语言常用命令详解(二)

    文章目录 前言常用命令go bug示例参数说明 go doc示例参数说明 go env示例 go fix示例 go fmt示例 go generate示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令&#xff0c;这些命令可以帮助您在Go开发中进行编译、测试、运行和…...

    2024/5/6 0:27:44
  15. 用欧拉路径判断图同构推出reverse合法性:1116T4

    http://cplusoj.com/d/senior/p/SS231116D 假设我们要把 a a a 变成 b b b&#xff0c;我们在 a i a_i ai​ 和 a i 1 a_{i1} ai1​ 之间连边&#xff0c; b b b 同理&#xff0c;则 a a a 能变成 b b b 的充要条件是两图 A , B A,B A,B 同构。 必要性显然&#xff0…...

    2024/5/6 7:24:04
  16. 【NGINX--1】基础知识

    1、在 Debian/Ubuntu 上安装 NGINX 在 Debian 或 Ubuntu 机器上安装 NGINX 开源版。 更新已配置源的软件包信息&#xff0c;并安装一些有助于配置官方 NGINX 软件包仓库的软件包&#xff1a; apt-get update apt install -y curl gnupg2 ca-certificates lsb-release debian-…...

    2024/5/6 7:24:04
  17. Hive默认分割符、存储格式与数据压缩

    目录 1、Hive默认分割符2、Hive存储格式3、Hive数据压缩 1、Hive默认分割符 Hive创建表时指定的行受限&#xff08;ROW FORMAT&#xff09;配置标准HQL为&#xff1a; ... ROW FORMAT DELIMITED FIELDS TERMINATED BY \u0001 COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMI…...

    2024/5/6 19:38:16
  18. 【论文阅读】MAG:一种用于航天器遥测数据中有效异常检测的新方法

    文章目录 摘要1 引言2 问题描述3 拟议框架4 所提出方法的细节A.数据预处理B.变量相关分析C.MAG模型D.异常分数 5 实验A.数据集和性能指标B.实验设置与平台C.结果和比较 6 结论 摘要 异常检测是保证航天器稳定性的关键。在航天器运行过程中&#xff0c;传感器和控制器产生大量周…...

    2024/5/6 7:24:03
  19. --max-old-space-size=8192报错

    vue项目运行时&#xff0c;如果经常运行慢&#xff0c;崩溃停止服务&#xff0c;报如下错误 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 因为在 Node 中&#xff0c;通过JavaScript使用内存时只能使用部分内存&#xff08;64位系统&…...

    2024/5/5 17:03:52
  20. 基于深度学习的恶意软件检测

    恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞&#xff0c;例如可以被劫持的合法软件&#xff08;例如浏览器或 Web 应用程序插件&#xff09;中的错误。 恶意软件渗透可能会造成灾难性的后果&#xff0c;包括数据被盗、勒索或网…...

    2024/5/6 21:25:34
  21. JS原型对象prototype

    让我简单的为大家介绍一下原型对象prototype吧&#xff01; 使用原型实现方法共享 1.构造函数通过原型分配的函数是所有对象所 共享的。 2.JavaScript 规定&#xff0c;每一个构造函数都有一个 prototype 属性&#xff0c;指向另一个对象&#xff0c;所以我们也称为原型对象…...

    2024/5/6 7:24:02
  22. C++中只能有一个实例的单例类

    C中只能有一个实例的单例类 前面讨论的 President 类很不错&#xff0c;但存在一个缺陷&#xff1a;无法禁止通过实例化多个对象来创建多名总统&#xff1a; President One, Two, Three; 由于复制构造函数是私有的&#xff0c;其中每个对象都是不可复制的&#xff0c;但您的目…...

    2024/5/6 7:24:01
  23. python django 小程序图书借阅源码

    开发工具&#xff1a; PyCharm&#xff0c;mysql5.7&#xff0c;微信开发者工具 技术说明&#xff1a; python django html 小程序 功能介绍&#xff1a; 用户端&#xff1a; 登录注册&#xff08;含授权登录&#xff09; 首页显示搜索图书&#xff0c;轮播图&#xff0…...

    2024/5/5 17:03:21
  24. 电子学会C/C++编程等级考试2022年03月(一级)真题解析

    C/C++等级考试(1~8级)全部真题・点这里 第1题:双精度浮点数的输入输出 输入一个双精度浮点数,保留8位小数,输出这个浮点数。 时间限制:1000 内存限制:65536输入 只有一行,一个双精度浮点数。输出 一行,保留8位小数的浮点数。样例输入 3.1415926535798932样例输出 3.1…...

    2024/5/6 16:50:57
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57