views:

153

answers:

2

I am currently evaluating Scala for future projects and came across something strange. I created the following constant for us in a JSP:

val FORMATED_TIME = "formatedTime";

And it did not work. After some experimenting I decided to decompile to get to the bottom of it:

private final java.lang.String FORMATED_TIME;

public java.lang.String FORMATED_TIME();
  Code:
   0:   aload_0
   1:   getfield    #25; //Field FORMATED_TIME:Ljava/lang/String;
   4:   areturn

Now that is interesting! Personally I have been wondering for quite a while why an inspector needs the prefix get and a mutator the prefix set in Java as they live in different name-spaces.

However it might still be awkward to explain that to the rest of the team. So is it possible to have a public constant without the inspector?

PS: No tag “Scala Java interoperability”?

A: 

I had a further look into the decompiled code and noted something else. The variables are not actually static. So my next idea was to use an object instead:

object KommenControler
{
   val FORMATED_TIME = "formatedTime";
} // KommenControler

But now things turn really ugly:

public final class ….KommenControler$ extends java.lang.Object implements scala.ScalaObject{

public static final ….KommenControler$ MODULE$;

private final java.lang.String FORMATED_TIME;

public static {};
  Code:
   0:   new #9; //class …/KommenControler$
   3:   invokespecial   #12; //Method "<init>":()V
   6:   return

public java.lang.String FORMATED_TIME();
  Code:
   0:   aload_0
   1:   getfield    #26; //Field FORMATED_TIME:Ljava/lang/String;
   4:   areturn

So I get an additional class ending on $ which has a singleton instance called MOUDLE$. And there is still the inspector. So the access to the variable inside a jsp becomes:

final String formatedTime = (String) request.getAttribute (….KommenControler$.MODULE$.FORMATED_TIME ());

This works as expected and I personally can live with it but how am I going to explain that to the team?

Of course if there is a simpler way I like to hear of it.

Martin
You should wrap it in a nice java object to abstract the ugly but necessary call. In fact, in Java, you should always encapsulate public static final constants in method call to avoid them being inlined at compilation.
paradigmatic
See this answer : http://stackoverflow.com/questions/3282653/how-do-you-call-a-scala-singleton-method-from-java/3445597#3445597
oluies
+6  A: 

This is because of the Uniform Access Principle, i.e.: Methods and Fields Are Indistinguishable

See this answer

In Scala 2.8.0 this means if you have a companion object, you lose your static forwarders)

If you have this in Scala:

//Scala
object CommonControler {
      val FORMATED_TIME = "formatedTime";
}

You may use it like this from Java

//Java

// Variables become methods
CommonControler$.MODULE$.FORMATED_TIME();
// A static forwarder is avaliable
CommonControler.FORMATED_TIME();

Also see the book Scala in Depth

Also note the @scala.reflect.BeanProperty for classes.

oluies
I have to check that again - because I am missing the forwarder. I did have a forwarder in the 2nd class I created.
Martin
I think I figured it out. If you have a class CommonControler and and object CommonControler then you don't get the static forwarders :-(.
Martin