Scala里在创建对象时,发现使用 new 类名() 和 new 类名 都可以创建对象,那二者有什么区别呢?
在这里定义了一个Student类,以创建这个类的对象来说明。
class Student(){
var name: String = _
var age: Int = _
}
使用 new 类名() 和 new 类名 分别创建对象如下:
//创建对象
val student01: Student = new Student()
val student02: Student = new Student
使用getClass和hashCode分别来查看类型和哈希值:
//查看类型,都是Student
println(student01.getClass)
println(student02.getClass)
//查看哈希值
println(student01.hashCode())
println(student02.hashCode())
运行结果:
类型都是Student,但是哈希值不同,说明创建的是两个不同的Student对象。
使用相同的方式再创建两个对象,并查看哈希值:
//使用相同的方式再创建两个对象
val student03: Student = new Student
val student04: Student = new Student()
//查看哈希值
println(student01.hashCode())
println(student02.hashCode())
运行结果:
studen01和student03的哈希值是相同的,studen02和student04的哈希值是相同的。
使用equals和eq来比较:
//使用equals来比较
println(student01.equals(student02)) //false
println(student01.equals(student03)) //false
//使用eq来比较
println(student01.eq(student02)) //false
println(student01.eq(student03)) //false
运行结果:
从结果可以看出:studen01和student03的地址是不同的,studen02和student04的地址也是不同的,所以创建的是4个不同的Student对象。
从最简原则来看:
从这里显然是看不出什么区别的,所以需要换个角度来看。我们知道,在Scala里函数或者方法是有至简原则的:如果是无参的函数,在调用的时候,可以不写(),如:
def myPrint() = {
println("hello")
}
可以用这样两种方式调用:
myPrint()
myPrint
运行结果:是一样的。
从构造器来看:
我们知道在Java里,类是有构造方法的,在创建对象的时候,是调用构造方法来创建的对象。在Scala里,类也是有构造方法的,在创建对象的时候也会调用构造方法,但是,在Scala里它不叫构造方法,它叫构造器,并且分为主构造器和辅助构造器两类。
像下面这样定义类,
class Student(){ //主构造器
var name: String = _
var age: Int = _
}
它的结构是:class是一个关键字,表明这是一个类;Student是类名;()里的是形参列表,因为这是无参的,所以只有();{}里的是类体;在Java里,构造方法的名字和类名是相同的,所以,在Scala里,它就直接把主构造器和类名写在一起了,不用再单独定义构造器了,然后像Java里的使用 this.name = name 和 this.age = age 来给属性赋值,这样就更简洁、更高效了,而()里的形参列表就是主构造器的形参列表了。
定义Teacher类帮助理解:
class Teacher(var name: String, var age: Int){ //主构造器
var sex: Char = _
var addr: String = ""
def this(name: String, age: Int, sex: Char){
this(name, age) //调用主构造器
this.sex = sex
}
def this(name: String, age: Int, addr: String){
this(name, age) //调用主构造器
this.addr = addr
}
}
此时,在创建对象时提示的可以选择的参数的个数和类型,其实就是在选择不同的构造器来创建对象,见图如下:
这时,再使用new 类名()和new 类名来创建对象就会报错,因为没有无参的构造器,所以就不能再这样创建对象了。
总结:
Scala里创建对象使用new 类名()和new 类名,本质上是没有区别的,都是调用同一个无参的构造器来创建对象,只是形式不同,new 类名()和new 类名是两种不同的调用形式。
注意:只有类里面有无参的构造器时,才能使用 new 类名() 和 new 类名 的方式来创建对象。