scala学习手记9 - =和==

= 赋值运算

scala的赋值运算和java的有着很大的不同。如a=b这样的赋值运算,在Java中返回值是a的值,在scala中返回的则是Unit。Unit是值类型,全局只存在唯一的值,即(),通常Unit只用来声明函数或方法的返回值,其他场景基本是没有意义的。这样就很容易导致一些错误地使用,比如a=b=c这样的赋值运算在java中是绝对可以的,但是在scala中运行就会报错。看一段代码:

var a, b, c = 1
a =  b=c
println(a)

上面这段代码还没有执行就在IDE中报错了,勉强执行下看看会报什么错:

报了类型不匹配的错误,因为在第一行代码中scala推断a是一个Int型的变量,后又将b=c的运算结果——一个Unit值——赋值给它,那当然会报错了。

即使只在scala中看赋值运算符“=”号也是一个比较奇怪的东西:它不是一个方法,在默认情况下不可以这样使用——a.=(1)。对于这一点暂时无法深入探究,以后有时间慢慢再看。

==运算

在java中,对于基本类型和引用类型的==运算有着不同的计算方式:

  • 对于基本类型来说,==运算比较的就是两边表达式的值;
  • 对于引用类型来说,==运算比较的是两边对象的引用而非是对象的值;在Java中比较对象的值使用的是equals方法。

在scala中没有对象,那么不论类型如何,==的运算都是面向值的。这一点由scala的Any类(scala中所有的类都是由它派生而来)提供了保证:它将==()方法实现为final的方法。因此在scala中进行值的比较就可以简单使用==运算,如果还有一些特殊化的比较,就需要改写equals方法了。如果想执行对于引用的比较可以使用eq()方法。看一下下面这段程序:

val str1 = "hello"
val str2 = "hello"
val str3 = new String("hello")

println(str1 == str2) // Equivalent to Java‘s str1.equals(str2)
println(str1 eq str2) // Equivalent to Java‘s str1 == str2
println(str1 == str3)
println(str1 eq str3)

程序的执行结果:

结果很清楚了。

---------------------------------------------------

今天学了scala的=和==,这两个运算和Java中对应符号的运算有着明显的不同,以后需要注意下。

#########

时间: 2024-11-08 19:19:16

scala学习手记9 - =和==的相关文章

scala学习手记17 - 容器和类型推断

关于scala的类型推断前面已经提到过多次.再来看一下下面这个例子: import java.util._ var list1: List[Int] = new ArrayList[Int] var list2 = new ArrayList[Int] list2 add 1 list2 add 2 var total = 0 for (index <- 0 until list2.size()) { total += list2.get(index) } println("Total i

scala学习手记8 - 自适应的默认做法

scala有一些默认做法,会让代码更简洁.更易读写,下面列出了这样几个特性: 1. 支持脚本.scala支持脚本,因此无须将所有的代码都放到类里.如果脚本可以满足需求,就将代码放到一个脚本里,无须再创建一个冗余的类. 2. return是可选的.如果没有写return关键字,方法调用会自动返回最后一个求值的表达式--如果它符合方法声明的返回值类型. 3. 分号":"是可选的.不必在每个语句的后面都写上分号,这样会使代码更简洁.如果语句太长或者包含多行的话可以换行继续写,scala能够识

scala学习手记38 - 方法命名约定和for表达式

方法命名约定 之前在学习<运算符重载>一节时曾经说过一个方法命名约定:方法的第一个字符决定了方法的优先级.现在再说另一个命名约定:如果方法以冒号(:)结尾,则调用目标是运算符后面的实例. 比如下面这个例子: class Cow { def ^(moon: Moon) = println("Cow jumped over the moon") } class Moon { def ^:(cow: Cow) = println("This cow jumped ove

scala学习手记23 - 函数值

scala的一个最主要的特性就是支持函数编程.函数是函数编程中的一等公民:函数可以作为参数传递给其他函数,可以作为其他函数的返回值,甚至可以在其它函数中嵌套.这些高阶函数称为函数值. 举一个简单的例子:从1到某个数求和.使用Java很容易实现: int sum(int max){ int result = 0; for (int i = 0; i <= max; i++) { result +=i; } return result; } 使用scala实现也没有多大区别. 现在再扩展下需求:对某

scala学习手记19 - Option类型

看到Option类型就知道这本教材应该要说那个了. 使用过guava后,应该知道guava中的Optional类的作用是什么.算了找下原始文档好了: Optional<T> is a way of replacing a nullable T reference with a non-null value. An Optional may either contain a non-null T reference (in which case we say the reference is &

scala学习手记13 - 类继承

在scala里,类继承有两点限制: 重写方法需要使用override关键字: 只有主构造函数才能往父类构造函数中传参数. 在java1.5中引入了override注解,但不强制使用.不过在scala中要想重写方法必须使用override关键字.如果确实重写了父类的方法又不使用override关键字的话,则会在编译时报错,提示没有使用override修饰符. scala的副构造函数必须调用主构造函数或是另一个副构造函数.只有在主构造函数中才能向父类的构造函数中传递数据.可以看出来主构造函数如同父类

scala学习手记10 - 访问修饰符

scala的访问修饰符有如下几个特性: 如果不指定访问修饰符,scala默认为public: 较之Java,scala对protected的定义更加严格: scala可以对可见性进行细粒度的控制. scala的默认访问修饰符 如果没有修饰符,scala会默认把类.字段.方法的访问修饰符当做public.如果要将之调整为private或protected,只需在前面添加对应的修饰符关键字即可.就如下面的程序: class Microwave{ def start() = println("star

scala学习手记40 - 使用case类

前面两节我们已经多次接触过case关键字了.case关键字不仅可以用在match/case中来执行模式匹配,也可以用来修饰类.不过用case修饰的类也主要是用来做模式匹配.在上一节曾经提到过match可以是Any类型的所有类,为什么还需要使用case关键字来修饰呢?假定有这样一个场景:我们要接收和处理股票交易信息,买卖消息通常会带有一些信息,诸如股票名称.数量.把这些信息存到对象里会很方便,但是如何对他们进行模式匹配呢?这时我们就会用到case类了.case类是模式匹配器(pattern mat

scala学习手记29 - 偏应用函数

调用函数可以说成是将函数应用于实参.如果传入所有的预期的参数,就完全应用了这个函数.如果只传入几个参数,就会得到一个偏应用函数. 偏应用函数是一个特殊的概念,在scala中它是使用val定义的,但是在使用时它却更像是一个函数.偏应用函数的定义更接近于python中有默认值的函数(scala实在是和python有太多相似的地方了). 先来看一个例子: import java.util.Date def log(date: Date, message: String) { //... println

scala学习手记18 - Any和Nothing

Any 前面已经有两次提到过:在scala中,Any类是所有类的超类. Any有两个子类:AnyVal和AnyRef.对应Java直接类型的scala封装类,如Int.Double等,AnyVal是它们的基类:对应引用类型,AnyRef是它们的基类. scala中,所有类的关系可以用下面这张图大致描述下: Any是一个抽象类,它有如下方法:!=().==().asInstanceOf().equals().hashCode().isInstanceOf()和toString().AnyVal没有