Scala语言是完全面向对象的语言,所以并没有静态的操作(即在Scala中没有静态的概念)。但是为了能够和Java语言交互(因为Java中有静态概念),就产生了一种特殊的对象来模拟类对象,该对象为单例对象,若单例对象名与类名一致,则称该单例对象这个类的伴生对象,这个类的所有“静态”内容都可以放置在它的伴生对象中声明
单例对象语法
基本语法
object Person{
val country:String="China"
}
案例实操
(1)单例对象采用object关键字声明
object Person {
var country: String = "China"
}
(2)单例对象对应的类称之为伴生类,伴生对象的名称应该和伴生类名一致
class Person {
var name: String = "bobo"
}
(3)单例对象中的属性和方法都可以通过伴生对象名(类名)直接调用访问
object Test {
def main(args: Array[String]): Unit = {
println(Person.country)
}
}
apply方法
类名+括号,调用对象的apply方法
- 说明
(1)通过伴生对象的apply方法,实现不使用new方法创建对象
(2)如果想让主构造器变成私有的,可以在()之前加上private
(3)apply方法可以重载
(4)Scala 中 obj(arg)的语句实际是在调用该对象的apply方法,即obj.apply(arg);用以统一面向对象编程和函数式编程的风格
(5)当使用new关键字构建对象时,调用的其实是类的构造方法,当直接使用类名构建对象时,调用的其实时伴生对象的apply方法
案例实操 ```scala object Test { def main(args: Array[String]): Unit = { //通过伴生对象的apply方法,实现不使用new关键字创建对象。 val p1 = Person() println(“p1.name=” + p1.name)
val p2 = Person(“bobo”) println(“p2.name=” + p2.name)
val p3 = Person.newPerson(“a1”) println(p3.name) } }
//如果想让主构造器变成私有的,可以在()之前加上private class Person private(cName: String) { var name: String = cName }
object Person { //这样实例化也行 def newPerson(cName: String): Person = new Person(cName: String)
def apply(): Person = { println(“apply空参被调用”) new Person(“xx”) }
def apply(name: String): Person = { println(“apply有参被调用”) new Person(name) } //注意:也可以创建其它类型对象,并不一定是伴生类对象
}
<a name="QH2ak"></a>
# 单例模式
<a name="acncf"></a>
## 饿汉式
类加载时就完成了初始化,所以类加载比较慢,但获取对象的速度快,不使用时就加载到内存,占用了资源
```scala
// 测试类
object TestSingleextends App {
val boss1 = Boss.getBoss
val boss2 = Boss.getBoss
// 1355531311 1355531311
print(boss1.hashCode() +" " + boss2.hashCode()) // 哈希值相等 对象为同一个 实现了单例
}
/*
底层代码
public SingleTon getInstance() {
if (s == null) {
s_$eq(new SingleTon());
}
return s();
}
*/
// 懒汉式
object Boss {
private var b: Boss= null //先赋值为null
def getBoss= {
if (b== null) {//判断不为null 才实例化对象
b= new Boss //在这里 实例化对象
}
b
}
}
class Boss private() { //Boss类的构造方法私有化
var name: String= _
println("懒汉式~~~")
}
懒汉式
等到引用时才会被加载
//测试类
object TestSingleextends App {
val b1 = Boss2.getBoss2
val b2 = Boss2.getBoss2
// 564160838 564160838 对象为同一个,形成了单例模式
print(b1.hashCode() +" " + b2.hashCode())
}
class Boss2 private() { //构造方法私有化
var age: Int= _
println("饿汉式~~~")
}
//饿汉式
object Boss2 {
private val b: Boss2 = new Boss2 //直接实例化对象
def getBoss2 = {
b
}
}