1
votes

In Java I'm trying to use a type defined in Scala, but I'm getting 'type mismatch' errors. I assume this is because of Java's type erasure, but is there some way to get around this?

In Scala I have this type

Type[T]

And an Action class which uses this type to define it's value type to guarantee the value is of the defined type.

class Action[T](tpe: Type[T], value: T)

Now when there is something like a BooleanType for example, then the Action only allows true of false values.

case object BooleanType extends Type[Boolean]
new Action(BooleanType, true) // ok
new Action(BooleanType, 1)    // compile error

We would like to be able to use this from Java as well. In Java I could define a type either as a class

class TimestampType implements Type[Long]

or as an enum to have a singleton like the 'case object's in Scala

enum LongType implements Type[Long] { LongType; }

But when I now try to use these in an Action

new Action(new TimestampType, 1L)
new Action(LongType.LongType, 1L)

both statements give a compile error

:12: error: type mismatch; found : TimestampType required: Type[Any] Note: Long <: Any (and TimestampType <: Type[Long]), but trait Type is invariant in type T. You may wish to define T as +T instead. (SLS 4.5) new Action(new TimestampType, 1L)

The cause is probably because the type erasure of the Java class. I have played with using +T and -T variance, but this does either not give the functionality which I want or does not compile. I also tried to use [T : ClassTag] for the Action class, but this does not resolve the issue.

Is there any way to be able to have Java implementations of Scala types? Is there a better way to try to enforce the type of the value is allowed or compatible with a defined Type?

1

1 Answers

3
votes

The problem is because you have specified the wrong type.You have declared it as:

class TimestampType implements Type[java.lang.Long]

but instead in scala, you do new Action(new TimestampType, 1L:scala.Long). java.lang.Long is different from scala.Long. Hence error.

The below works: In Java:

public class IntTyp implements Typ<scala.Int> {}

In scala,

val b = new Action[Int](new IntTyp, 1)

or vice-versa:

public class LongTyp implements Typ<Long> {}
val c = new Action[java.lang.Long](new LongTyp, 1L)