我目前正在修復對象字段內的private final val
在被訪問前未初始化的非常奇怪的錯誤。代碼的位置可以在https://github.com/mdedetrich/soda-time/blob/master/jvm/src/main/scala/org/joda/time/chrono/GregorianChronology.scala#L12-L33找到。對象內未初始化的字段
您可以通過拉動上述回購軟件,然後運行sodatimeJVM/console
,然後在控制檯中運行import org.joda.time._來模擬此錯誤。 DateTime.now()。minusDays(10)
的代碼已經在這裏
object GregorianChronology {
private final val MILLIS_PER_YEAR = (365.2425 * DateTimeConstants.MILLIS_PER_DAY).toLong
private final val MILLIS_PER_MONTH = (365.2425 * DateTimeConstants.MILLIS_PER_DAY/12).toLong
private final val DAYS_0000_TO_1970 = 719527
private final val MIN_YEAR = -292275054
private final val MAX_YEAR = 292278993
private final val INSTANCE_UTC = getInstance(DateTimeZone.UTC)
private final val cCache = new ConcurrentHashMap[DateTimeZone, Array[GregorianChronology]]()
def getInstanceUTC(): GregorianChronology = INSTANCE_UTC
def getInstance(): GregorianChronology = getInstance(DateTimeZone.getDefault, 4)
def getInstance(zone: DateTimeZone): GregorianChronology = getInstance(zone, 4)
def getInstance(zone: DateTimeZone, minDaysInFirstWeek: Int): GregorianChronology = {
var _zone: DateTimeZone = zone
if (_zone == null) {
_zone = DateTimeZone.getDefault
}
var chrono: GregorianChronology = null
var chronos: Array[GregorianChronology] = cCache.get(_zone)
發佈的最後一行,即var chronos: Array[GregorianChronology] = cCache.get(_zone)
拋出一個java.lang.NullPointerException
。該值爲空是cCache
但是這是沒有意義的,因爲它清楚地被初始化爲private final val cCache = new ConcurrentHashMap[DateTimeZone, Array[GregorianChronology]]()
。如果我打開"-Xcheckinit"
斯卡拉然後告訴我scala.UninitializedFieldError: Uninitialized field: GregorianChronology.scala: 19
哪些指向private final val cCache = new ConcurrentHashMap[DateTimeZone, Array[GregorianChronology]]()
。這不是很有用,因爲我知道這個值沒有初始化,問題是我不知道爲什麼。由於它是最終的val,我認爲它應該是初始化的第一個值之一,特別是在getInstance
曾經被調用之前。
我知道我可以使價值懶惰來解決它,然而會引入一個不需要的性能命中。更重要的是,等效的Java版本private static final ConcurrentHashMap<DateTimeZone, GregorianChronology[]> cCache = new ConcurrentHashMap<DateTimeZone, GregorianChronology[]>()
工作得很好。
謝謝,感覺如此愚蠢的錯過! – mdedetrich