/**
* 这个类提供了一个简单的方法来获取相等字符串的唯一对象。由于符号是拘禁的,所以可以使用引用相等来比较它们。使用Scala内置的引号机制可以轻松创建`Symbol`的实例。
* 例如,Scala术语`'mysym`将按以下方式调用`Symbol`类的构造函数:`Symbol("mysym")`。
*
* @author Martin Odersky, Iulian Dragos
* @since 1.7
*/
final class Symbol private(val name: String) extends Serializable {
/**
* 将Symbol转为字符串
*/
override def toString(): String = "'" + name
@throws(classOf[java.io.ObjectStreamException])
private def readResolve(): Any = Symbol.apply(name)
override def hashCode = name.hashCode()
//比较引用
override def equals(other: Any) = this eq other.asInstanceOf[AnyRef]
}
//伴生对象,继承了缓存抽象类,具体实现抽象在UniquenessCache中
object Symbol extends UniquenessCache[String, Symbol] {
override def apply(name: String): Symbol = super.apply(name)
//string -> Symbol,从字符串生成Symbol
protected def valueFromKey(name: String): Symbol = new Symbol(name)
//Symbol -> Option[String] 从Symbol生成字符串
protected def keyFromValue(sym: Symbol): Option[String] = Some(sym.name)
}
/**
* 这是私有的,因此它不会出现在标准库API中
*/
private[scala] abstract class UniquenessCache[K, V >: Null] {
import java.lang.ref.WeakReference
import java.util.WeakHashMap
import java.util.concurrent.locks.ReentrantReadWriteLock
//读写锁
private val rwl = new ReentrantReadWriteLock()
//读锁
private val rlock = rwl.readLock
//写锁
private val wlock = rwl.writeLock
//存储映射的map,是一个弱引用。(无论当前内存是否足够,都会回收掉只被弱引用关联的对象)
private val map = new WeakHashMap[K, WeakReference[V]]
//string -> Symbol
protected def valueFromKey(k: K): V
//Symbol -> Option[String]
protected def keyFromValue(v: V): Option[K]
//使用Symbol("hello")会调用super.apply(name),所以会调用此方法
def apply(name: K): V = {
def cached(): V = {
//加读锁从map中获取已有的Symbol对象
rlock.lock
try {
val reference = map get name
//获取到则直接返回,没有则null
if (reference == null) null
else reference.get // will be null if we were gc-ed
}
finally rlock.unlock
}
def updateCache(): V = {
//加写锁更新map中的字符串对应的Symbol对象
wlock.lock
try {
//若缓存中已有,则直接返回,否则获取该字符串对应的Symbol对象,并更新map,然后返回Symbol对象
val res = cached()
if (res != null) res
else {
//如果我们不从map映射中删除旧的字符串键,我们可能会以一个字符串作为键,而将另一个字符串作为Symbol中的name字段,这可能会导致意外的GC行为和重复的Symbols
map remove name
val sym = valueFromKey(name) //生成Symbol对象
map.put(name, new WeakReference(sym))
sym
}
}
finally wlock.unlock
}
val res = cached()
//若缓存中没有,则更新,否则直接返回Symbol对象
if (res == null) updateCache()
else res
}
def unapply(other: V): Option[K] = keyFromValue(other)
}