Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using Java generic method from Scala

I'm having problem understanding Scalac's error message in this example:

Bean.java

public class Bean {
  static public class Attribute<T> {
    public final String name;
    public Attribute(String name) {this.name = name;}
    // equals and hashcode omitted for simplicity
  }

  public <T> void set(Attribute<T> attribute, T value) {}

  public static Attribute<Long> AGE = new Attribute<Long>("age");
}

Test.scala

object Test {
  def test() {
    val bean = new Bean();
    bean.set(Bean.AGE, 2L);
  }
}

compiling yeilds this (tried with scalac 2.9.2):

Test.scala:4: error: type mismatch;
 found   : Bean.Attribute[java.lang.Long]
 required: Bean.Attribute[Any]
Note: java.lang.Long <: Any, but Java-defined class Attribute is invariant in type T.
You may wish to investigate a wildcard type such as `_ <: Any`. (SLS 3.2.10)
bean.set(Bean.AGE, 2L);
              ^
one error found

why is it requiring Attribute[Any]? Doing same in Java works fine

thanks

like image 550
eprst Avatar asked Aug 03 '13 03:08

eprst


People also ask

How do I use generic in Scala?

To use a generic class, put the type in the square brackets in place of A . The instance stack can only take Ints. However, if the type argument had subtypes, those could be passed in: Scala 2.

Does Scala support generics?

The classes that takes a type just like a parameter are known to be Generic Classes in Scala. This classes takes a type like a parameter inside the square brackets i.e, [ ].

Can I use polymorphism in generics?

The polymorphism applies only to the 'base' type (type of the collection class) and NOT to the generics type.

How do you invoke a generic method?

To call a generic method, you need to provide types that will be used during the method invocation. Those types can be passed as an instance of NType objects initialized with particular . NET types.


1 Answers

The error is due to mismatch between java.lang.Long and scala Long.

Bean.AGE is of type Bean.Attribute[java.lang.Long]. Hence the scala compiler expects a java.lang.Long as the other argument. But you are passing is 2L which is scala.Long and not java.lang.Long. Hence it shows error.

Doing this will work as expected:

 b.set(Bean.AGE,new java.lang.Long(23))

Thanks to @senia, the below is a better alternative:

bean.set[java.lang.Long](Bean.AGE, 23)
bean.set(Bean.AGE, 23:java.lang.Long)
like image 134
Jatin Avatar answered Sep 19 '22 14:09

Jatin