问题描述:

I am working with some old Java libraries that use collections not specifying type parameters (e.g. Eclipse draw2d) in Scala.

Suppose that you have a java class (that you cannot modify) like this:

// A.java

package com.example.test;

import java.util.ArrayList;

public class A extends ArrayList {} // not ArrayList<Object>, just ArrayList

If you want to work with class A in Java, you can do this:

// B.java

import com.example.test.A;

public class B {

public static void main(String[] args) {

A a = new A();

a.add(1);

}

}

javac B.java succeed with some warnings:

Note: C.java uses unchecked or unsafe operations.

Note: Recompile with -Xlint:unchecked for details.

However, the identical thing with Scala is impossible:

// C.scala

import com.example.test.A

object C {

def main(args: Array[String]): Unit = {

val a = new A()

a.add(1)

}

}

scalac C.scala emit an error:

C.scala:6: error: type mismatch;

found : Int(1)

required: E

a.add(1)

^

How can I use this class in Scala?

网友答案:

Well what you can do is:

val a = new A
val ls = a.asInstanceOf[java.util.List[Any]]
ls.add(1)

But again you will not be able to use other methods from A. I am still unsure on how you would be able to access A methods. The reference (in Change logs says):

A raw type in Java such as ArrayList is translated to ArrayList[_], which is a shorthand for ArrayList[T] forSome { type T }

So the scala compiler always takes it as A extends ArrayList[E] forSome {type E} and am unsure on how the type can be escaped (at compile time).

网友答案:

I found a solution:

// C.scala
import com.example.test.A
import java.util.ArrayList

object C {
  def main(args: Array[String]): Unit = {
    val a = new A()
    a.asInstanceOf[ArrayList[Any]].add(1)    // a.add(1)
    println(a.size())
  }
}

This code solved the problem!

But I still wonder how ArrayList[Nothing] -> ArrayList[Any] conversion is possible in Scala, while Array is invariant. Moreover, Scala accepts ArrayList[Any] -> ArrayList[Nothing] conversion too!

相关阅读:
Top