深入解析Kotlin类与对象:构造、伴生、单例全面剖析
前言
本篇文章将带您了解Kotlin编程中的重要概念:类及构造函数、访问修饰符、伴生对象和单例模式。就像搭积木一样,我们会逐步揭开这些概念的面纱,让您轻松理解它们的作用和用法。无论您是编程新手还是有经验的开发者,本文都将为您提供有趣而易懂的内容,帮助您更好地掌握Kotlin中类与对象的重要知识点。让我们一起开始这段有趣的学习之旅吧!
一、Kotlin 的类以及构造函数
1、声明一个类
当你使用 class
关键字在 Kotlin 中声明一个类时,其基本的语法格式如下所示:
class ClassName {// 类的成员变量和方法在这里定义
}
2、关于Kotlin类的继承和接口实现的规则
(1)继承父类
如果一个类有父类,你可以在类的声明中使用冒号 :
后面跟着父类的名称。这称为类的继承。例如:
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivityclass MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)// 在这里可以进行一些初始化操作}
}
-
继承父类无参构造函数:如果父类有一个无参构造函数,子类可以省略括号,并且不需要在子类中声明构造函数。这适用于父类的构造函数没有参数的情况,或者所有参数都有默认值。
-
继承父类有参构造函数:如果父类的构造函数有参数,或者你想在子类中添加自己的构造函数,就需要根据具体情况使用括号并传递必要的参数。
(2)默认父类
如果一个类没有显式声明父类,它的默认父类是 Any
类,而不是 Object
类。Any
是 Kotlin 根类层次结构的顶层类型。所有的 Kotlin 类都直接或间接地继承自 Any
类。
Any
类的声明如下:
public open class Any
在 Kotlin 中,默认情况下,所有类都隐式地继承自 Any
类,即使你没有明确指定。因此,以下两个类声明是等价的:
class MyClass
class MyClass : Any()
这就是为什么你在 Kotlin 中无需显式指定父类,而默认情况下所有类都已经继承自 Any
。
需要注意的是,Any
类定义了一些通用方法,如 equals
、hashCode
和 toString
,因此所有的 Kotlin 类都会具备这些方法。
(3)接口实现
在 Kotlin 中,可以在类的声明后面使用冒号 :
来实现一个或多个接口。你不需要显式使用 implements
关键字。例如:
import android.os.Bundle
import android.view.View
import android.widget.Button
import androidx.appcompat.app.AppCompatActivityclass MainActivity : AppCompatActivity(), View.OnClickListener {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val button = findViewById<Button>(R.id.button)button.setOnClickListener(this)}override fun onClick(v: View?) {when (v?.id) {R.id.button -> {// 在这里定义按钮点击事件的逻辑}}}
}
在上面的示例中,我们首先让 MainActivity
类实现了 View.OnClickListener
接口,并重写了其中的 onClick
方法。然后,我们在 onCreate
方法中使用 setOnClickListener(this)
将当前 MainActivity
对象作为按钮的点击监听器。
在 Kotlin 中,你是可以先写接口后写父类,或者先写父类后写接口,都是完全合法的。在类的声明中,继承父类和实现接口的顺序可以根据你的需求进行灵活安排。
3、open 关键字的作用
在 Kotlin 中,默认情况下,类是 public
和 final
的,这意味着它们对外部可见,并且不能被继承。如果你希望其他类能够继承这个类,你需要使用 open
关键字来声明这个类,使它变成可继承的。
在 Kotlin 中,修饰符的含义如下:
public
:表示该成员(类、函数、属性等)在任何地方都可见。final
:表示类、函数或属性不能被继承或覆盖(重写),在类级别指的是类不能被继承。open
:用于修饰类、函数或属性,表示它们可以被继承或覆盖。
如果你想要创建一个可被继承的类,你需要使用 open
修饰符。
例如,当你想在 Android 应用中创建一个可被继承的 MainActivity
类时,你需要在类的声明前面加上 open
修饰符,以允许其他类继承它。这样,其他类就可以继承 MainActivity
并在子类中进行扩展。
以下是一个示例,展示如何在 Android 应用中创建一个可被继承的 MainActivity
类:
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivityopen class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)// 在这里可以进行一些初始化操作}
}
在这个示例中,我们创建了一个名为 MainActivity
的类,继承自 AppCompatActivity
,这是 Android 中用于创建活动(Activity)的基类。注意,在类的声明中,我们使用了 open
修饰符,允许其他类继承这个 MainActivity
。
其他类可以继承这个 MainActivity
并在子类中进行扩展,例如:
class CustomActivity : MainActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// 在这里可以进行自定义的初始化操作}
}
在上面的示例中,CustomActivity
类继承自 MainActivity
,并在子类中重写了 onCreate
方法,实现了自定义的初始化操作。
总结,通过使用 open
修饰符,你可以在 Android 应用中创建一个可被继承的基类,让其他类能够继承它并在子类中添加自己的功能。
4、主构造函数和次构造函数
构造函数是用于创建对象的特殊方法,它在对象创建时被调用,通常用于执行初始化操作。在 Kotlin 中,类可以有一个主构造函数和多个次构造函数。
(1)主构造函数
当涉及到在 Kotlin 类中创建实例时,主构造函数扮演着重要的角色。主构造函数允许在对象被实例化时接收参数,并且对对象的属性进行初始化。以下是关于主构造函数的概要:
- 声明方式:主构造函数是类定义的一部分,紧随类名后面的括号中可以包含参数列表。如果主构造函数没有其他修饰符,那么括号可以省略。
- 参数传递:主构造函数的参数可以在整个类范围内使用,不仅限于初始化代码块。你可以将这些参数直接用于属性的初始化。
- 初始化代码块:主构造函数也可以包含初始化代码块,使用
init
关键字定义。在这个代码块中,你可以编写在对象初始化时执行的代码。
以下是一个示例,展示了如何声明主构造函数、使用参数初始化属性,并在初始化代码块中执行逻辑,其中使用了自定义视图类 CustomView
:
class CustomView(context: Context, attrs: AttributeSet): View(context, attrs) {private val paint: Paint = Paint()init {paint.color = Color.BLACK}
}
在上述示例中,CustomView
类继承自 View
,并在主构造函数中接收了 context
和 attributeSet
参数。
在类的主体中,声明了一个名为 paint
的私有属性,并在初始化时进行了属性初始化。使用了 Paint
类,这是 Android 中用于绘制图形和文本的工具类。
在类的 init
块中,设置了 paint
的颜色为黑色(Color.BLACK
)。这将确保 paint
对象在视图实例化时就被配置为黑色,以便在后续的绘制操作中使用。
当创建 CustomView
的实例时,会触发 init
块中的代码执行,从而完成属性的初始化设置。init
块是一个在对象实例化时执行初始化代码的地方,它允许你在构造函数中接收参数,并在 init
块中执行必要的初始化逻辑。在自定义视图类中,你可以使用 init
块来确保对象在使用之前处于正确的状态。
(2)次构造函数
次构造函数是在 Kotlin 中用于提供额外的构造函数选项的一种方式。它允许你在同一个类中定义多个不同参数集的构造函数,以满足不同的初始化需求。次构造函数通常调用主构造函数或者其他次构造函数,确保共享的初始化逻辑被重复使用。
以下是关于次构造函数的一些重要信息:
- 声明方式:次构造函数通过
constructor
关键字声明,紧随其后的括号内包含参数列表。次构造函数可以有不同的参数集,但不能直接初始化属性。 - 调用主构造函数:在次构造函数内部,你可以使用
this()
调用主构造函数,确保共享的初始化逻辑被执行。调用主构造函数时,可以传递相应的参数。 - 调用其他次构造函数:在次构造函数内部,你也可以使用
this()
调用同一个类中的其他次构造函数。这样可以避免重复编写初始化逻辑。
以下是一个示例,展示了如何在 CustomView
类中使用次构造函数:
class CustomView : View {constructor(context: Context) : this(context, null, 0)constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {initialize(context, attrs, defStyleAttr)}private fun initialize(context: Context, attrs: AttributeSet?, defStyleAttr: Int) {// 在这里执行初始化操作}}
在上面的示例中,CustomView
类继承自 Android 中的 View
类,并且有三个构造函数:
- 第一个构造函数接收一个
context
参数,这是主构造函数。它通过调用次构造函数,为attrs
和defStyleAttr
提供默认值。 - 第二个构造函数接收
context
和attrs
参数,调用了具有更多参数的次构造函数。 - 第三个构造函数接收
context
、attrs
和defStyleAttr
参数,它是主要的构造函数。它通过调用父类View
的构造函数来实现,并在构造函数内部调用了initialize
函数来执行额外的初始化操作。
(3)大家来找茬
可以尝试将下面示例代码放到编译器中,会发现编译不通过, super
处会提示 “Primary constructor call expected”。问题出在了哪里?
class CustomView(context: Context) : View(context) {constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) {initialize(context, attrs, 0)}constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {initialize(context, attrs, defStyleAttr)}private fun initialize(context: Context, attrs: AttributeSet?, defStyleAttr: Int) {// 在这里执行初始化操作}}
错误消息 “Primary constructor call expected” 意味着在构造函数的调用位置需要调用主构造函数,但实际上没有调用。
在 Kotlin 中,如果一个类有一个主构造函数,那么所有的次构造函数必须委托给主构造函数。这是语言的规定,确保类的初始化能够始终通过主构造函数完成。
在我们的代码中,主构造函数是 class CustomView(context: Context) : View(context)
这一行。由于它是一个主构造函数,所有的次构造函数必须通过 this()
来调用主构造函数。因此,不能在次构造函数中使用 super
关键字来调用父类的构造函数。
以下是修正后的代码示例,满足了 Kotlin 的构造函数规定:
class CustomView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : View(context, attrs, defStyleAttr) {constructor(context: Context) : this(context, null, 0) constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)init {initialize(context, attrs, defStyleAttr)}private fun initialize(context: Context, attrs: AttributeSet?, defStyleAttr: Int) {// 在这里执行初始化操作}
}
在这个修正后的代码中,主构造函数是 class CustomView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : View(context, attrs, defStyleAttr)
,并且所有的次构造函数都通过 this()
来委托主构造函数。统一在 init
添加初始化操作,以满足我们的需求。
(4)@JvmOverloads
注解
使用了 @JvmOverloads
注解来为 CustomView
类的构造函数生成所有可能的参数组合,以简化构造函数的使用。这样,你可以使用主构造函数,也可以选择性地使用次构造函数。
我们将上述代码再次改造一下:
class CustomView @JvmOverloads constructor(context: Context,attrs: AttributeSet? = null,defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {init {initialize(context, attrs, defStyleAttr)}private fun initialize(context: Context, attrs: AttributeSet?, defStyleAttr: Int) {// 在这里执行初始化操作}
}
使用这个示例,你可以这样创建一个 CustomView
实例:
val customView1 = CustomView(context)
val customView2 = CustomView(context, attrs)
val customView3 = CustomView(context, attrs, defStyleAttr)
@JvmOverloads
是 Kotlin 中的一个注解,用于在编译器级别生成多个重载版本的函数或构造函数,以便在 Java 代码中更方便地使用。这个注解通常用于改善 Kotlin 类在 Java 代码中的互操作性。
在特定情况下,Kotlin 的函数或构造函数可能具有默认参数,这使得在 Kotlin 中调用它们非常方便,因为可以省略部分参数。但在 Java 中,调用具有默认参数的 Kotlin 函数会变得不那么直观,因为 Java 不直接支持 Kotlin 的默认参数语法。
这时,@JvmOverloads
就派上用场了。当你在 Kotlin 函数或构造函数上使用 @JvmOverloads
注解时,Kotlin 编译器会自动为每个省略参数的版本生成一个重载版本,以便在 Java 代码中使用。这样,Java 开发者就可以根据需要传递不同数量的参数,而不必理解或设置 Kotlin 的默认参数。
具体来说,对于构造函数来说,@JvmOverloads
会在编译时为每个可能的参数组合生成一个单独的构造函数,以确保 Java 开发者能够使用所有参数组合。
总结:@JvmOverloads
是一个用于改善 Kotlin 代码在 Java 中互操作性的注解,它为具有默认参数的函数或构造函数生成重载版本,使得 Java 开发者能够更方便地使用这些函数或构造函数。
(5)init 函数,父类的构造函数与次构造函数之间调用顺序
- 首先,会执父类的
init
块(如果有的话) - 其次,会执行父类的构造函数(主构造函数或者被次构造函数调用的构造函数)。
- 然后,会执行当前类的
init
块(如果有的话)。 - 最后,会执行当前类的次构造函数(如果有的话)。
以下是一个示例来说明这个调用顺序:
open class Parent {init {println("Parent's init block")}constructor() {println("Parent's constructor")}
}class Child : Parent {constructor() : super() {println("Child's constructor")}init {println("Child's init block")}
}fun main() {val obj = Child()
}
在这个示例中,当创建 Child
类的实例时,首先会调用 Parent
类的 init
块,其次是 Parent
类的构造函数,然后执行 Child
类的 init
块,最后执行 Child
类的次构造函数。因此,输出将是:
Parent's init block
Parent's constructor
Child's init block
Child's constructor
二、访问修饰符
在 Kotlin 中,访问修饰符用于控制类、接口、函数、属性等成员的可见性。Kotlin 提供了一些访问修饰符,用于指定成员在哪些范围内可见。以下是常见的访问修饰符:
public
(默认):没有显式指定访问修饰符时,默认为public
。在这种情况下,成员对所有其他代码都可见。private
:成员只在声明它的文件中可见。私有成员对同一文件中的其他类都不可见。protected
:成员在声明它的类及其子类中可见。但在同一包内的其他类中不可见。internal
:成员对于同一模块内的所有代码都可见。模块是一组一起编译的 Kotlin 文件。它更多的去用于我们现在做一些项目的结构化的扩展的时候去使用这个修饰符。
示例:
class MyClass {private val privateVar = 1protected val protectedVar = 2internal val internalVar = 3val publicVar = 4 // 默认为 public
}fun main() {val obj = MyClass()println(obj.internalVar) // 可以访问,因为处于同一模块内println(obj.publicVar) // 可以访问,因为是 public// 下面的代码不能编译通过,因为 private 和 protected 变量不在可见范围内// println(obj.privateVar)// println(obj.protectedVar)
}
注意:
- 对于顶层声明(不在类内部的声明),只有
public
和internal
修饰符有效。 internal
修饰符在 Kotlin 中非常有用,它允许模块内的代码访问成员,同时限制了模块之间的访问。private
和protected
对于顶层声明(不在类内部的声明)是无效的,因为它们只对类内部的成员可见性起作用。
综上所述,访问修饰符用于控制代码中成员的可见性范围,确保代码的封装和安全性。
补充一下,什么是模块?
每当创建一个 module,这就是一个模块。如果你的一个变量名通过internal修饰的话,在同一个模块内的时候,是可以互相调用的,但是跨模块的话,你是无法访问到这个变量的。这就是 kotlin 的这个访问修饰符,它更多的去用于我们现在做一些项目的结构化的扩展的时候去使用这个修饰符。
三、伴生对象
在 Kotlin 中,每个类都可以有一个伴生对象(Companion Object),它是该类的一个特殊对象实例。伴生对象的成员可以像 Java 静态成员一样在类级别上访问,不需要通过类的实例来调用。伴生对象通常用于创建类级别的静态成员、工厂方法、单例模式等。
在 JAVA 中,我们经常看到这样的一段代码,就是工具类,里面定义了一些的静态方法,可以直接用工具类的类名 .
方法名,去调用它。如下所示:
public class StringUtils {public static final String EMPTY = "";public static boolean isEmpty(CharSequence cs) {return cs == null || cs.length() == 0;}public static boolean isNotEmpty(CharSequence cs) {return !StringUtils.isEmpty(cs);}
}
但是在 kotlin 中是没有静态方法的,Kotlin 要怎么改写呢?
方法有两种,第一种办法是我们在《Kotlin 代码与 Java 代码集成》中介绍过,使用 @JvmStatic
注释暴露 Kotlin 类的静态方法。
那么第二种方法就是现在要介绍的伴生对象 Companion Object ,它必须被写在一个类的内部,作为这个类的伴生对象。伴生对象可以包含成员函数、属性和初始化代码块,类似于 Java 中的静态成员。它的一个主要作用是允许在不创建类实例的情况下访问这些成员,就像访问静态成员一样。
那么我们来改写一下:
class StringUtils {companion object {const val EMPTY = ""fun isEmpty(cs: CharSequence?): Boolean {return cs.isNullOrEmpty()}fun isNotEmpty(cs: CharSequence?): Boolean {return !isEmpty(cs)}}
}
在上面的示例中,StringUtils 类中定义了一个伴生对象,其中包含一个常量 EMPTY 和 两个方法isEmpty
和isNotEmpty
。那么就可以在类级别上直接访问伴生对象的成员和方法,就像访问类的静态成员和静态方法一样。
在 Java 代码中调用,如下所示:
public class JavaExample {public static void main(String[] args) {String str = "";boolean isEmpty = StringUtils.Companion.isEmpty(str);boolean isNotEmpty = StringUtils.Companion.isNotEmpty(str);System.out.println("isEmpty: " + isEmpty);System.out.println("isNotEmpty: " + isNotEmpty);}
}
注意,StringUtils.Companion
中的 Companion
是伴生对象的默认名称,因为我们并未显式地为我们的伴生对象命名,伴生对象的名称可以省略,那么此时使用默认的名称 Companion
。
实际上伴生对象在编译好以后会在这个类的内部生成一个静态对象。叫companion
的对象,那么我们Java在调用的时候,实际上是通过这个类的companion
对象去调用companion
内部的一些变量。
如果你为伴生对象显式命名,例如 MyCompanion
,那么需要使用该名称来访问伴生对象的成员。以下是一个使用了命名伴生对象的示例:
class StringUtils {companion object MyCompanion {const val EMPTY = ""fun isEmpty(cs: CharSequence?): Boolean {return cs.isNullOrEmpty()}fun isNotEmpty(cs: CharSequence?): Boolean {return !isEmpty(cs)}}
}
在 Java 代码中调用,如下所示:
public class JavaExample {public static void main(String[] args) {String str = "";boolean isEmpty = StringUtils.MyCompanion.isEmpty(str);boolean isNotEmpty = StringUtils.MyCompanion.isNotEmpty(str);System.out.println("isEmpty: " + isEmpty);System.out.println("isNotEmpty: " + isNotEmpty);}
}
四、单例
半生对象在 Kotlin 中还有一个非常有用的特性,就是可以用于声明单例。在前面的文章中,我们已经介绍了通过 object
关键字来创建匿名的内部类,这种方式其实也可以用来实现单例。然而,更加推荐的写法是利用伴生对象来创建单例。
使用伴生对象来实现单例具有许多优点:
- 线程安全: 伴生对象的属性和方法在类加载时进行初始化,确保了线程安全。这样即使在多线程环境下也能保证只有一个实例被创建。
- 延迟初始化: 伴生对象的属性和方法是在首次访问时才会被初始化,这也被称为"惰性初始化"。这种方式能够节省资源,只有在实际需要时才会创建实例。
- 清晰可见: 伴生对象使得单例模式的实现更加清晰和易于理解。它将单例的代码组织在一起,使得代码结构更加整洁。
总的来说,虽然在 Kotlin 中可以使用 object
关键字来创建单例,但更加推荐使用伴生对象来实现。这种方式不仅更加优雅,还能够带来诸多优势,如线程安全和延迟初始化等。如果你正在考虑实现单例模式,不妨考虑使用伴生对象来达到更好的效果。
以下是如何使用伴生对象来实现单例模式的示例:
class Single private constructor() {companion object {fun get(): Single {return Holder.instance}}private object Holder {val instance = Single()}
}
Single
类的主构造函数被声明为私有,这意味着外部无法直接通过构造函数来实例化该类。- 在
Single
类的伴生对象中,我们定义了一个名为get
的方法,用于获取Single
类的单例实例。该方法返回了一个Holder
内部对象的实例,这是通过Holder.instance
访问的。 - 内部的
Holder
对象的实例化是通过 Kotlin 中的对象声明(object
)实现的。由于 Kotlin 的对象声明在首次访问时就会被初始化,且只会被初始化一次,这确保了线程安全的单例创建。
上述代码展示了一种在 Kotlin 中使用伴生对象来创建单例的方式,这是一种非常常见的做法。这种方式结合了私有的主构造函数和内部对象,确保了单例的线程安全性和延迟初始化。
相关文章:
![](https://img-blog.csdnimg.cn/f60ba46a447a480683ac76fbf59aed7e.png#pic_center)
深入解析Kotlin类与对象:构造、伴生、单例全面剖析
前言 本篇文章将带您了解Kotlin编程中的重要概念:类及构造函数、访问修饰符、伴生对象和单例模式。就像搭积木一样,我们会逐步揭开这些概念的面纱,让您轻松理解它们的作用和用法。无论您是编程新手还是有经验的开发者,本文都将为…...
![](https://img-blog.csdnimg.cn/05526439a76c49e1b252ff8b6cddb81b.png)
JavaScript构造函数
1、构造函数: 是一个函数,是通过new运算符进行调用,生成一个特殊的对象并返回。 function 函数名([参数]){ this.属性名 ‘属性值’ ... this.属性名 function([参数]){ 函数体语句 } } 通常情况下,建议构造函数的首字母大写 …...
![](https://www.ngui.cc/images/no-images.jpg)
手写嵌入式操作系统(基于stm8单片机)
#include <stc8h.h> #include <intrins.h> #define MAX_TASKS 2 //简化方面,我们当前操作系统只有2个task #define MAX_TASK_DEP 32unsigned char idata task_sp[MAX_TASKS]; // 任务的堆栈指针 unsigned char idata task_stack[MAX_TASKS][MAX_TASK_DEP];// 每个…...
![](https://www.ngui.cc/images/no-images.jpg)
vue3.3 ~
defineModel 原本: // 1 defineProps({modelValue: {type: Number,required: true,default: 0} })defineProps([modelValue]) // 2 const emit defineEmits([update:modelValue])现在: const value defineModel<number>({ default: 0 })defin…...
![](https://img-blog.csdnimg.cn/03d3c25585544c058a2fda299ea187b3.png)
滑动窗口实例4(将x减到0的最小操作数)
题目: 给你一个整数数组 nums 和一个整数 x 。每一次操作时,你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。 如果可以将 x 恰好 减到 0 ,返回 …...
![](https://img-blog.csdnimg.cn/cbb66bf5214845338e0c456b722e7f39.png)
数据库原理及应用(MySQL)
建议大屏观看,避免格式错误,影响观感 目录 第一章 数据库系统概述 1.数据库系统概述 1.1.信息 1.2.数据 1.3.信息和数据之间的联系 1.4.数据库(DB) 1.5.数据库管理系统(DBMS) 1.6.数据库管理系统的…...
![](https://img-blog.csdnimg.cn/1046c94bac694315b67b251650df48d4.png)
初识Maven(一)命令行操作和idea创建maven工程
Maven 是 Apache 软件基金会组织维护的一款专门为 Java 项目提供**构建**和**依赖**管理支持的工具。 构建过程包含的主要的环节:- 清理:删除上一次构建的结果,为下一次构建做好准备 - 编译:Java 源程序编译成 *.class 字节码文件…...
![](https://www.ngui.cc/images/no-images.jpg)
MHA高可用配置及故障切换
1.什么是 MHA MHA(MasterHigh Availability)是一套优秀的MySQL高可用环境下故障切换和主从复制的软件。 MHA 的出现就是解决MySQL 单点的问题。 MySQL故障切换过程中,MHA能做到0-30秒内自动完成故障切换操作。 MHA能在故障切换的过…...
![](https://img-blog.csdnimg.cn/ec9c16c1e7b648f7a4e7cf401bfdff30.png)
FPGA/IC秋招面试题 1(解析版)
分享个人觉得遇到还不错的题,后续有会继续补充。。。 以下题目均来自网络平台,用于学习交流如有侵权立马删除!!! 1. Verilog语言中,下面哪些语句不可被综合() A. #delay语句 B. initial语句 C. always语句 D. 用gen…...
![](https://img-blog.csdnimg.cn/0bac6487bf594a299cfd1df78960351a.png)
华为云 异构数据迁移
数据库和应用迁移 UGO(Database and Application Migration UGO,以下简称为UGO)是专注于异构数据库结构迁移的专业服务。可将源数据库中的DDL、DML和DCL一键自动转换为华为云GaussDB/RDS的SQL语法,通过数据库评估、对象迁移两大核…...
![](https://www.ngui.cc/images/no-images.jpg)
wininet,winhttp,xmlhttprequest,各版本区别 《转》
一、标准API接口WinINet(Microsoft Windows Internet)和WinHTTP(Microsoft Windows HTTP) 实现Http访问,微软提供了二套API:WinINet, WinHTTP(分别封装于system32目录下的wininet.dll和winhttp.dll内) 二者主要区别在于后者更为安…...
![](https://img-blog.csdnimg.cn/6da046c676594a42be3dab0d40b7eb79.png)
朴素,word,任何参考文献导入endnote
朴素,word,任何参考文献导入endnote 注意:对于以下这几种不做阐述,看其他帖子都有讲述: 这里的参考文献指的是类似于: [1]. Li Y, Lu Y, Huo X, et al. Bandgap tuning strategy by cations and halide io…...
![](https://img-blog.csdnimg.cn/59b0d719a3404345b3f7cc786cfc1668.png)
数学建模--三维图像绘制的Python实现
目录 1.绘制三维坐标轴的方法 2.绘制三维函数的样例1 3.绘制三维函数的样例2 4.绘制三维函数的样例3 5.绘制三维函数的样例4 6.绘制三维函数的样例5 1.绘制三维坐标轴的方法 #%% #1.绘制三维坐标轴的方法 from matplotlib import pyplot as plt from mpl_toolkits.mplot3…...
![](https://img-blog.csdnimg.cn/cba7092e1b554be7bfa4661443006e6b.png)
Spring Cloud Alibaba-Feign整合Sentinel
第1步: 引入sentinel的依赖 <!--sentinel客户端--> <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> 第2步: 在配置文件中开启Feign对Sentinel的…...
![](https://img-blog.csdnimg.cn/58b6db489b924232a142e7c200b5aeb7.png)
zabbix配置钉钉告警、和故障自愈
钉钉告警python脚本 cat python20 #!/usr/bin/python3 #coding:utf-8 import requests,json,sys,os,datetime # 机器人的Webhook地址 webhook"钉钉" usersys.argv[1] textsys.argv[3] data{"msgtype": "text","text": {"conten…...
![](https://www.ngui.cc/images/no-images.jpg)
Web安全测试(五):XSS攻击—存储式XSS漏洞
一、前言 结合内部资料,与安全渗透部门同事合力整理的安全测试相关资料教程,全方位涵盖电商、支付、金融、网络、数据库等领域的安全测试,覆盖Web、APP、中间件、内外网、Linux、Windows多个平台。学完后一定能成为安全大佬! 全部文章请访问专栏:《全栈安全测试教程(0基…...
![](https://img-blog.csdnimg.cn/fd6258e0aba84ef18fc89e6acec5971b.png)
本地PC机通过SSH方式远程Jetson
1. 检测电脑是否安装openSSH 以管理员身份运行powershell终端输入以下命令: Get-WindowsCapability -Online | ? Name -like OpenSSH*若没有安装OpenSSH,会出现如下图提示: 输入Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.…...
![](https://www.ngui.cc/images/no-images.jpg)
面向对象 学习黑马视频(03)
1.内存分区模型 /* 面向对象编程** 内存分区模型* 1.代码区:存放函数体的二进制代码,由操作系统进行管理的* 2.全局区:存放全局变量和静态变量以及常量* 3.栈区:由编译器自动分配释放,存放函数的参数值…...
![](https://img-blog.csdnimg.cn/img_convert/4ab09026885a95a9f5a25b129fa5a38e.jpeg)
FinClip 支持创建 H5应用类小程序;PC 终端 优化升级
FinClip 的使命是使您能够通过小程序解决关键业务流程挑战,并完成数字化转型。不妨让我们看看本月产品与市场发布亮点,是否有助于您实现目标。 产品方面的相关动向👇👇👇 FinClip 支持创建 H5应用类小程序 近期我们…...
![](https://img-blog.csdnimg.cn/1cdc1b99f8b344d8a4e1201606c01c08.png)
YOLOV8实例分割——详细记录环境配置、自定义数据处理到模型训练与部署
前言 Ultralytics YOLOv8是一种前沿的、最先进的(SOTA)模型,它在前代YOLO版本的成功基础上进行了进一步的创新,引入了全新的特性和改进,以进一步提升性能和灵活性。作为一个高速、精准且易于操作的设计,YO…...
![](https://www.ngui.cc/images/no-images.jpg)
2309ddocx02文档
风格,页眉和页脚等内容与主要分开,允许在起始文档中放大量自定义,然后在生成文档中显示. 打开文档 from docx import Document document Document() document.save("test.docx")真正打开文档 要用文件名打开文档: document Document("existing-document-f…...
![](https://img-blog.csdnimg.cn/img_convert/c22788b7e7b5300b15ca497d732482b1.png)
第一章初识微服务
文章目录 认识微服务单体架构分布式架构需要考虑的问题 微服务微服务的具体架构微服务技术对比企业中的技术需求 总结 服务拆分注意事项 认识微服务 随着互联网行业的发展,对服务的要求也越来越高,服务架构也从单体架构逐渐演变为现在流行的微服务架构。…...
![](https://www.ngui.cc/images/no-images.jpg)
微信小程序电影票订票小程序软件设计与实现
摘 要 我们的生活水平正在不断的提高,然而提高的一个重要的侧面表现就是更加注重我们的娱乐生活。电影是我们都喜欢的一种娱乐方式,各式各样的电影给我们带来的喜悦也是大不相同的。带来快乐的同时也因为其复杂、繁琐的流程让电影爱好者们变得烦躁起来。…...
![](https://img-blog.csdnimg.cn/3076efa055504a0bae935b8f626792d8.png)
Redis 缓存预热+缓存雪崩+缓存击穿+缓存穿透
面试题: 缓存预热、雪萌、穿透、击穿分别是什么?你遇到过那几个情况?缓存预热你是怎么做的?如何造免或者减少缓存雪崩?穿透和击穿有什么区别?他两是一个意思还是载然不同?穿适和击穿你有什么解…...
![](https://www.ngui.cc/images/no-images.jpg)
java 面试题汇总整理
java有哪四种引用类型 在Java中,有四种引用类型,用于控制对象的生命周期和垃圾回收行为。这些引用类型包括: 强引用(Strong Reference): 强引用是最常见的引用类型,它们是默认的引用类型。当一…...
![](https://img-blog.csdnimg.cn/d9784c5c983145639f70f5a70239889e.png)
淘宝开放平台免审核接入 获取淘宝卖家订单列表订单详情API
taobao.open.trades.sold.get 搜索当前会话用户作为卖家已卖出的交易数据(只能获取到三个月以内的交易信息) 1. 返回的数据结果是以订单的创建时间倒序排列的。 注意:type字段的说明,如果该字段不传,接口默认只查4种类…...
![](https://www.ngui.cc/images/no-images.jpg)
Mybatis中的关系映射
1.一对一的映射关系 一对一关系(One-to-One)表示两个实体对象之间存在唯一的关联关系。例如,一个学生只能拥有一个身份证。在 MyBatis 中,我们可以使用结果嵌套或一对一映射来处理一对一关系。 1.1 创建模型类和Vo类 package com…...
![](https://img-blog.csdnimg.cn/68d0ef7d7afb4f1586deb42465508d31.png)
领域建模之数据模型设计方法论
本文通过实际业务需求场景建模案例,为读者提供一种业务模型向数据模型设计的方法论,用于指导实际开发中如何进行业务模型向数据模型转化抽象,并对设计的数据模型可用性、扩展性提供了建议性思考。通过文章,读者可以收获到业务模型…...
![](https://www.ngui.cc/images/no-images.jpg)
springboot毕业生信息招聘平台设计与实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 毕业生信息招聘平台,主要的模块包括查看管理员;首页、个人中心、企业管理、空中宣讲会管理、招聘岗位管理、毕业生管理…...
![](https://img-blog.csdnimg.cn/212aa4e18fbb42e09b1e64848e892753.png)
开发前期准备工作
开发前期准备工作 文章目录 开发前期准备工作0 代码规范0.1 强制0.2 推荐0.3 参考dao:跟数据库打交道service:业务层,人类思维解决controller:抽象化 0.4 注释规范0.5 日志规范0.6 专有名词0.7 控制层统一异常统一结构体控制层提示…...
![](/images/no-images.jpg)
wordpress 宠物模板/广告推广平台网站有哪些
stm32 USB-HID移植[复制链接]stm32芯片的设计确实很恶心简单举两个例子:1. STM32F103芯片的USB和CAN中断和RAM共用,导致无法同时使用USB和CAN。2.STM32F105芯片的USB的从机需要接VBUS脚,而103的不用接都可以;103的软连接的通过IO端…...
![](/images/no-images.jpg)
做竞价的网站需要做外部链接吗/seo网站培训班
在Qt4中的desinger中涉及到控件Q3ListBox,但是在make的时候出现提示错误,是说无法解析到外部符号等等。 原因是:因为这个是Qt3的控件,Qt4并没有做到很好的支持,所以必须加上QT3的suuport 在.pro文件中加入一行…...
![](/images/no-images.jpg)
flash代码做网站教程/上海公关公司
计算机编程术语: 参考网址:https://blog.csdn.net/linear_luo/article/details/52318820 application 应用程式 应用、应用程序 application framework 应用程式框架、应用框架 应用程序框架 architecture 架构、系统架构 体系结构 argument 引数&am…...
![](/images/no-images.jpg)
广州市住房和城乡建设厅网站首页/德芙巧克力软文推广
信号量的基本介绍: 信号量的本质是⼀种数据操作锁,它本⾝不具有数据交换的功能,⽽是通过控制其他的通信资源(⽂件,外部设备)来实现进程间通信, 它本只是⼀种外部资源的标识。信号量在此过程中负…...
![](/images/no-images.jpg)
广东今日头条新闻/网络推广优化品牌公司
使用 ALTER SECURITY LABEL COMPONENT 语句向当前数据库中的一个现有的安全标签构件中 添加一个或多个元件。该语句是 SQL ANSI/ISO 标准的扩展。 image.png 用法 只有 DBSECADM 可以声明 ALTER SECURITY LABEL COMPONENT 语句,此语句定义现有安 全标签构件的新元件…...
青海住房和城乡建设部网站/长沙市网站制作
如何在ZEMAX和MATLAB之间通信本文内容:1如何在MATLAB和ZEMAX中设置通信链接2如何为MATLAB设置ZEMAX DDE工具箱3常见问题及解答Zemaxand Matlab : 强大的配对Zemax具有内置的DDE(动态数据交换)服务器,因而允许其他的windows程序和zemax函数之间建立链接。…...