Что Скала пытается мне сказать и как мне это исправить?[обязательный: java.util.List [? 0] где тип? 0] - PullRequest
6 голосов
/ 20 июля 2010

Я нахожусь в процессе изучения Scala, и сегодня я чувствовал себя уверенно, представляя его в одном из наших проектов.

Приложение выполняет много JPA / Hibernate, и я начал реализовывать один из интерфейсов Java в Scala. Все шло хорошо, пока я не попытался перевести какой-нибудь unittest-код в Scala.

Я много использую Easymock, код довольно понятен. Я предполагаю, что проблема в том, что Scala не позволяет мне возвращать типизированный java.util.List, где он ожидает нетипизированный. К сожалению, я не знаю, как заставить Scala приводить что-то, что ожидает параметры типа к чему-то без.

Код, который иллюстрирует / воспроизводит мою проблему:

package some.package.name

import java.util.ArrayList
import java.util.List
import javax.persistence.Query
import org.easymock.EasyMock._
import org.junit.Assert._
import org.junit.Test

class MyGreatScalaTest {

  @Test
  def testSomething() : Unit = {

    val mockQuery: Query = createMock(classOf[Query])
    val mockResult: List[String] = new ArrayList[String]
    mockResult.add("great value")

    expect(mockQuery.getResultList).andReturn(mockResult)
    replay(mockQuery)

    assertEquals(
      (mockQuery.getResultList.asInstanceOf[List[String]]).get(0),
      "great value")

    verify(mockQuery)
  }
}

, которая выдает следующую ошибку компилятора:

[WARNING]  found   : java.util.List[String]
[WARNING]  required: java.util.List[?0] where type ?0
[WARNING]     expect(mockQuery.getResultList).andReturn(mockResult)
[WARNING]                                               ^     

Как видите, мне нужен макет для реализации интерфейса javax.persistence.Query , который возвращает java.util.List.

1 Ответ

11 голосов
/ 21 июля 2010

javax.persistence.Query#getResultList возвращает raw type List, в отличие от * cooked8 типа, подобного List[String]. Java произвела большую часть стандартной библиотеки в версии 1.5, но должна была иметь обратную совместимость с двоичными файлами и исходными текстами, написанными для 1.4.

Компилятор Scala допускает такие неприятные типы, но переводит его в List[_], что сокращенно для List[?0] forSome { type ?0 }. Это известно как экзистенциальный тип, и это означает, что тип элемента List является каким-то конкретным типом, даже если мы точно не знаем, какой именно!

Easymock требует, чтобы аргумент andReturn был того же типа, что и тип аргумента, передаваемого expect, нашему проблемному экзистенциальному типу.

Я ожидаю, что это решит проблему:

expect(mockQuery.getResultList.asInstanceOf[List[String]]).andReturn(mockResult)
...