我正在使用一个系统,该系统需要使用事务初始化许多对象,并且出于超出此问题范围的原因,这些事务必须传递到构造函数中。像这样:
trait Mutable
class Txn(i: Int) {
def newID(implicit m: Mutable): Int = i
override def finalize(): Unit = println("Finalised " + i)
}
class User(t0: Txn) extends Mutable {
val id = t0.newID(this)
}
现在,我担心垃圾收集事务存在问题:
val u = new User(new Txn(1234))
System.gc() // hmmm, nothing seems to happen?
所以我的问题是:
t0
构造函数参数是否曾经被垃圾收集过,还是在这里创建了内存泄漏?在一个等效的Java代码中,我想我会有这样的东西:public class User implements Mutable {
final int id;
public User(Txn t0) {
id = t0.newID(this);
}
}
并且我确定
t0
已收集。但这在Scala案中是真的吗?如果没有,如何确保
t0
被垃圾回收?请记住,我必须将事务作为构造函数参数传递,因为User
类实现了必须传递到Txn
的方法中的某些特征,因此在构造newID
之前不能调用这些方法(例如User
)。之前,我尝试过使用大量的
lazy
相互依赖的val来构造使用用户对象之外的事务的所有东西,但这确实很麻烦。例如,这已经是一半不可读了,它会产生堆栈溢出:trait User extends Mutable { def id: Int }
def newUser(implicit tx: Txn): User = {
lazy val _id: Int = tx.newID(u)
lazy val u = new User { val id: Int = _id } // oops, should be lazy val id!
u
}
val u = newUser(new Txn(1234))
您可以想象,确实很烂,编译器在这里找不到丢失的惰性val的问题,因此我绝对希望使用构造函数arg变体。
最佳答案
如果绝对必要,建议您使用javap
来查看该类已编译到的内容。避免将构造函数参数转换为类参数的一些规则:
def
或lazy val
上使用它。 val (a, b) = f(x)
)。 val
或var
。 关于scala - 构造函数参数是否得到GC校验?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8643219/