Reputation: 11
While trying to port old code running Rhino engine to Nashorn in Java 8, I got the trouble, static properties/methods cannot be accessed from running js script. If I use Rhino, it runs perfectly. I don't know what happens with the implementation of the new Nashorn engine.
import javax.script.*;
public class StaticVars {
public static String myname = "John\n";
public static void main(String[] args) {
try{
ScriptEngine engine;
ScriptEngineManager manager = new ScriptEngineManager();
engine=System.getProperty("java.version").startsWith("1.8")?
manager.getEngineByName("Nashorn") : //j1.8_u51
manager.getEngineByName("JavaScript"); //j1.7
engine.put("staticvars", new StaticVars());
engine.eval("print(staticvars.myname);");
//print "John" if ran with java 7
//print "undefined" if ran with java 8
} catch(Exception e){e.printStackTrace();}
}
}
Upvotes: 1
Views: 2602
Reputation: 31
This is not the way js should work. I think this is a design bug in Nashorn. Assume you have a mixed util passing vars from some java runtime system to the js script. This object contains one static method fmtNumber(someString) and one object method jutil.getFormVar(someString). The users don't need to know that Java is serving this platform. You simply tell them jutil is a "system hook" belonging to the framework foo. As a user of this framework I don't care about if its static or not. I am a js developer, i don't know about static or not. I want to script something real quick. This is how the code in rhino looks like.
var x = jutil.getFormVar("x");
print(jutil.fmtNumber(x));
Now in nashorn I have to distinguish between them. Even worse I even have to educate my users to distinguish between them and teach them java terms, which they might not know because this is what an abstraction layer is all about: a self containing system without the need to know the underlying mechanisms. This distinction is way to much cognitive overload and you did not think about other usecases than java developers scripting for them self which they probably wont to because the already know a good language called Java. You are thinking form your implementation as a Java developer when instead you should think how you could use the power of the Java Plattform in the background, hiding all the nasty details from JS developers. What would a webdeveloper say if he needs to distinguish between the static C++ implementation in the browser?
Upvotes: 0
Reputation: 4595
In Nashorn, you can't access class static members through class instances. There are multiple ways to get at statics. You can obtain a type object that acts as both a constructor and as a static namespace, much like a type name acts in Java:
var StaticVars = Java.type("StaticVars"); // use your full package name if you have it
print(StaticVars.myname);
Or, pass in a java.lang.Class
object and use the .static
pseudo-property to access the statics:
engine.put("StaticVarsClass", StaticVars.class);
followed by:
var StaticVars = StaticVarsClass.static;
print(StaticVars.myname);
in the script. In general, .static
is the inverse operation to .class
:
var BitSet = Java.type("java.util.BitSet");
var bitSetClass = BitSet.class; // produces a java.lang.Class object, just like in Java
print(BitSet === bitSetClass.static); // prints true
var bitSet = new BitSet(); // type object creates a new bitset when used as a constructor
var thisWontWork = new bitSetClass(); // java.lang.Class can't be used as a constructor.
As you can see, we distinguish three concepts:
java.lang.Class
. They aren't special, and you only can use the Class
API on them (.getSuperclass()
, .getName()
, etc.)This actually produces least ambiguity, as everything is in its place, and maps most closely to Java platform idioms.
Upvotes: 3