在Scala中,类的主构造函数没有显式主体,但是从类主体隐式定义.那么,如何区分字段和本地值(即构造函数方法的本地值)?
例如,请使用以下代码片段,这是"Scala中的编程"中的一些示例代码的修改形式:
class R(n: Int, d: Int) {
private val g = myfunc
val x = n / g
val y = d / g
}
Run Code Online (Sandbox Code Playgroud)
我的理解是,这将生成一个包含三个字段的类:私有"g",以及公共"x"和"y".但是,g值仅用于计算x和y字段,并且除了构造函数范围之外没有任何意义.
所以在这个(公认的人为的)例子中,你如何为这个构造函数定义局部值?
我正在使用"Scala for the Impatient"练习5.7,我需要创建一个类名为 Person的类:构造函数上的字符串,并且有两个属性firstName和lastName由名称分隔的空格填充.我的第一次试验是:
class Person(name:String) {
private val nameParts = name.split(" ")
val firstName = nameParts(0)
val lastName = nameParts(1)
}
Run Code Online (Sandbox Code Playgroud)
问题是,现在nameParts仍然是一个在类中始终可见的私有字段,实际上应该只存在于构造函数的本地环境中.我想要的Java相当于:
class Person{
private final String firstName;
private final String lastName;
Person(String name){
final String[] nameParts = name.split(" ");
firstName = nameParts[0];
lastName = nameParts[1];
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,nameParts只存在构造函数,这正是我的目标.有关如何在Scala中完成此操作的任何提示?
注意:我最终找到了更"Scalesque"的方式:
class Person(name:String) {
val firstName::lastName::_ = name.split(" ").toList
}
Run Code Online (Sandbox Code Playgroud)
但我还是希望得到我的问题的答案.
我在Scala中有一个系统,有很多同步线程和系统调用.该系统存在一些问题,因为内存使用量会随着时间的推移而增加
下图显示了一天的内存使用情况.当它达到极限时,过程关闭,我放一只看门狗再次恢复它.
我定期运行命令
jcmd <pid> GC.run
Run Code Online (Sandbox Code Playgroud)
这使得内存缓慢增加,但泄漏仍然发生.
我用jvisualvm进行了分析,比较了不同时刻,40分钟三角洲.下图显示了这两个时刻之间的比较.请注意,有一个增加一些像类的实例ConcurrentHashMap$HashEntry,SNode,WeakReference,char[]和String许多类的包装scala.collection.concurrent.

什么可能导致内存泄漏?
编辑1:调查JVisualVM,我注意到了在TriedMap中的CNode和INode类的对象,它在sbt.TrapExit $ App类中实例化.这是对象层次结构图:

以下代码摘自Martin Odersky等人的Scala编程书.它定义了一个理性类型:
class Rational(n: Int, d: Int) {
require(d != 0)
private val g = gcd(n.abs, d.abs)
val numer = n / g
val denom = d / g
...
private def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b)
}
Run Code Online (Sandbox Code Playgroud)
这里值g仅在隐式构造函数初始化字段numer和denom时使用.假设程序员知道它不会在其他任何地方使用.在上面的例子中,它在构造Rational对象后仍然可以访问.这意味着它也将占用空间,因为它是一个私有字段,而不是构造函数的局部变量.
我的问题是如何更改此代码,以便g仅在构造时使用然后丢弃?