【发布时间】:2009-08-02 13:09:07
【问题描述】:
我正在阅读“Scala 编程”一书,在第 6 章中实现类 Rational 时遇到了一些问题。
这是我的 Rational 类的初始版本(基于本书)
class Rational(numerator: Int, denominator: Int) {
require(denominator != 0)
private val g = gcd(numerator.abs, denominator.abs)
val numer = numerator / g
val denom = denominator / g
override def toString = numer + "/" + denom
private def gcd(a: Int, b: Int): Int =
if(b == 0) a else gcd(b, a % b)
// other methods go here, neither access g
}
这里的问题是字段 g 在类的生命周期内仍然存在,即使再也不会被访问。这个问题可以通过运行下面的模拟程序看到:
object Test extends Application {
val a = new Rational(1, 2)
val fields = a.getClass.getDeclaredFields
for(field <- fields) {
println("Field name: " + field.getName)
field.setAccessible(true)
println(field.get(a) + "\n")
}
}
它的输出将是:
Field: denom
2
Field: numer
1
Field: g
1
我在Scala Wiki 找到的解决方案涉及以下内容:
class Rational(numerator: Int, denominator: Int) {
require(denominator != 0)
val (numer, denom) = {
val g = gcd(numerator.abs, denominator.abs)
(numerator / g, denominator / g)
}
override def toString = numer + "/" + denom
private def gcd(a: Int, b: Int): Int =
if(b == 0) a else gcd(b, a % b)
// other methods go here
}
在这里,字段 g 仅在其块中是本地的,但是,在运行小型测试应用程序时,我发现了另一个字段 x$1,它保留了由 (numer, denom) 组成的元组的副本!
Field: denom
2
Field: numer
1
Field: x$1
(1,2)
有没有办法在Scala中用上述算法构造一个有理数,而不会造成任何内存泄漏?
谢谢,
弗拉维乌·西普西根
【问题讨论】:
-
谢谢,很抱歉再次提问:)。链接帖子中的答案澄清了我的问题。
-
您确认
denom和numer真的是值吗?如果它们是def denom = x$1._2形式的“唯一”访问器方法,我一点也不感到惊讶。 -
不是内存泄漏,是内存开销。
标签: scala memory-leaks