6

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

0

1 Answer 1

8

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)
Sign up to request clarification or add additional context in comments.

5 Comments

@PrinceJohnWesley Oops. Yes. Corrected. Thanks.
Don't you think 23: java.lang.Long looks a little bit better? Or even b.set[java.lang.Long](Bean.AGE, 23).
@senia You are a genius. I have learnt a lot from your answers over past few months here at SO :-)
thank you, this makes sense although doesn't make me happy. Do you see any way to hide explicit type specification and make this Java API look better for the Scala users? I'd expect scalac to try Predef.long2Long before failing but it doesn't happen, looks like it tries long2LongConflict instead
@eprst Well implicits only work for functions with one argument and not more. Had that method been in scala, you could have defined it as: def set[T](att:Attribute[T])(value:T){}. And then later ` set(age)(2L)` would have worked. Thanks to currying. But in your case, I do not know of any other better option

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.