2013-07-22 1 views
0

Я не хотел писать много кода шаблона, поэтому решил написать общий метод для lazy-init.Общая ленивая инициализация с помощью scala

import java.util._ 
import concurrent.ConcurrentHashMap 

object GenericsTest { 
    val cache: ConcurrentHashMap[Long, 
    ConcurrentHashMap[Long, 
     ConcurrentHashMap[Long, 
     ConcurrentHashMap[Long, Long]]]] = new ConcurrentHashMap() 

    def main(args: Array[String]) { 
    val x = get(cache, 1)(() => new ConcurrentHashMap()) 
    val y = get(x, 1)(() => new ConcurrentHashMap()) 
    val z = get(y, 1)(() => new ConcurrentHashMap()) 
    } 

    def get[B, A](map: ConcurrentHashMap[A, B], a: A)(factory:() => B): B = { 
    if (map.containsKey(a)) { 
     map.get(a) 
    } else { 
     val b = factory() 
     map.put(a, factory()) 
     b 
    } 
    } 
} 

Этот пример работает только с жестко Long, но не с общей , что может быть проблема? Может быть, есть еще один способ сделать такие вещи?

+0

Можете ли вы показать, что именно это не работает, и объяснить, каким образом это не удается? –

ответ

1

Ошибка в этой строке:

val x = get(cache, 1)(() => new ConcurrentHashMap()) 

Проблема заключается в том, что тип 1 является Int.

У нас есть этот метод подписи:

get[A, B](map: ConcurrentHashMap[A, B], a: A)(factory:() => B): B 

Типы параметров, передаваемых в этом проблемном вызова являются (B является то, что давно вложенный тип, это не имеет значения сейчас):

ConcurrentHashMap[Long, B] and Int 

поэтому компилятор рассчитывает, что A должен быть ближайшим общим предком Долгосрочные и Int, что составляет AnyVal, поэтому в конце концов он будет использовать переданные параметры с типами:

ConcurrentHashMap[AnyVal, B] and AnyVal 

Но ConcurrentHashMap инвариантно в его первый параметр типа, поэтому кэш вал не может быть использован в качестве ConcurrentHashMap [AnyVal, B ], поэтому компилятор выдаст сообщение об ошибке (удалить длинную вложенную параметр типа часть, это сейчас не важно):

found : java.util.concurrent.ConcurrentHashMap[Long, ...] 
required: java.util.concurrent.ConcurrentHashMap[AnyVal, ...] 
Note: Long <: AnyVal, but Java-defined class ConcurrentHashMap is invariant in type K. 

чтобы это исправить, необходимо пройти второй параметр как Long:

val x = get(cache, 1L)(() => new ConcurrentHashMap()) 
val y = get(x, 1L)(() => new ConcurrentHashMap()) 
val z = get(y, 1L)(() => new ConcurrentHashMap()) 

 Смежные вопросы

  • Нет связанных вопросов^_^