2010-10-05 11 views
8

Ich werte derzeit Scala für zukünftige Projekte aus und bin auf etwas Seltsames gestoßen. Ich habe die folgende Konstante für uns in einer JSP erstellt:Scala-Konstanten in Java verwenden

val FORMATED_TIME = "formatedTime"; 

Und es hat nicht funktioniert. Nach einigen Experimenten beschloss ich, zu dekompilieren, um zum Ende zu kommen:

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 

Jetzt ist das interessant! Persönlich frage ich mich seit einiger Zeit, warum ein Inspektor das Präfix und einen Mutator das Präfix in Java benötigt, da sie in verschiedenen Namensräumen leben.

Es könnte jedoch immer noch peinlich sein, dies dem Rest des Teams zu erklären. Ist es also möglich, eine öffentliche Konstante ohne den Inspektor zu haben?

Antwort

11

Dies ist wegen der Uniform Access Principle, das heißt: Methoden und Felder nicht zu unterscheiden sind

Siehe this answer

In Scala 2.8.0 bedeutet dies, wenn Sie ein Begleiter Objekt haben, können Sie Ihre statisch verlieren Forwarder)

Wenn Sie dies in Scala haben:

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

Sie können es so aus Java

//Java 

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

nachschauen Auch das Buch Scala in Depth

Auch die @scala.reflect.BeanProperty für Klassen beachten.

+0

Ich muss das noch einmal überprüfen - weil ich Vermisse den Spediteur.Ich hatte einen Spediteur in der 2. Klasse, die ich geschaffen habe. – Martin

+1

Ich denke, ich habe es herausgefunden. Wenn Sie eine Klasse CommonControler und ein Objekt CommonControler haben, erhalten Sie die statischen Weiterleitungen nicht :-(. – Martin

1

Ich hatte einen weiteren Blick in den dekompilierten Code und bemerkte etwas anderes. Die Variablen sind nicht wirklich statisch. So war meine nächste Idee, statt ein Objekt zu verwenden:

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

Aber jetzt die Dinge wirklich hässlich:

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 bekomme ich eine zusätzliche Klasse auf $ enden, die eine Singleton-Instanz hat moudle $ genannt. Und da ist noch der Inspektor. So ist der Zugriff auf die Variable in einer jsp wird:

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

Dies funktioniert wie erwartet und ich persönlich kann damit leben, aber wie soll ich, dass das Team erklären?

Natürlich, wenn es einen einfacheren Weg gibt, höre ich gerne davon.

+1

Sie sollten es in ein nettes Java-Objekt wickeln, um den hässlichen aber notwendigen Anruf zu abstrahieren. Tatsächlich sollten Sie in Java immer statische statische Endkonstanten in Methodenaufruf einkapseln, um zu vermeiden, dass sie bei der Kompilierung inline sind. – paradigmatic

+0

Siehe diese Antwort: http://stackoverflow.com/questions/3282653/how-do-you-call-a-scala-singleton-method-from-java/3445597#3445597 – oluies