2015-09-20 106 views
1

虽然试图将运行Rhino引擎的旧代码移植到Java 8中的Nashorn,但遇到了麻烦,静态属性/方法无法从运行js脚本访问。如果我使用犀牛,它运行完美。我不知道实施新的Nashorn发动机会发生什么。从Nashorn引擎中的js代码访问静态Java变量

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();} 
    } 
} 

回答

2

在Nashorn中,您无法通过类实例访问类静态成员。有多种方法可以获得静态。您可以获取同时充当一个构造函数和一个静态命名空间的类型的对象,就像一个类型名称Java中的作用:

var StaticVars = Java.type("StaticVars"); // use your full package name if you have it 
print(StaticVars.myname); 

或者,传递一个java.lang.Class对象,并使用.static伪属性来访问静力学:

engine.put("StaticVarsClass", StaticVars.class); 

依次为:

var StaticVars = StaticVarsClass.static; 
print(StaticVars.myname); 
脚本

。在一般情况下,.static是逆操作.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. 

正如你所看到的,我们区分三个概念:

  • 运行时类的对象,这是java.lang.Class实例。他们不是特别的,你只能用他们的Class API(.getSuperclass().getName()等)的类本身
  • 实例
  • 类型的对象(即你可以访问实例成员正常的对象),这是两个名称空间都代表它们所代表的类的静态成员,以及构造函数。 Java中最接近的等同于源代码中使用的类的名称;在JavaScript中它们是实际的对象。

这实际上产生的模糊性最小,因为所有的东西都在它的位置,并且最接近Java平台的习惯用法。

+0

它的工作原理!只需要对代码进行一些更改。顺便说一句,这些方法不向后兼容Rhino.Thanks! – truongdao

0

这不是js应该工作的方式。我认为这是Nashorn的一个设计错误。假设你有一个混合的util将vars从一些java运行时系统传递给js脚本。该对象包含一个静态方法fmtNumber(someString)和一个对象方法jutil.getFormVar(someString)。用户不需要知道Java正在为此平台提供服务。你只需告诉他们jutil是属于框架foo的“系统钩子”。作为这个框架的用户,我不关心它的静态与否。我是一名js开发人员,我不知道静态与否。我想快速编写一些脚本。这就是犀牛代码的样子。

var x = jutil.getFormVar("x"); 
print(jutil.fmtNumber(x)); 

现在在nashorn我必须区分它们。更糟糕的是,我甚至不得不教育我的用户区分它们并教授它们可能不知道的java术语,因为这是一个抽象层所关心的:一个自我包含的系统,而不需要知道底层机制。这种区别是很多认知过载的方式,您不会考虑其他用例,而不是java开发人员为他们自己编写脚本,因为他们可能不会这样做,因为已经知道一种称为Java的良好语言。您正在考虑以Java开发人员的身份实施,相反,您应该考虑如何在后台使用Java Plattform的强大功能,从JS开发人员那里隐藏所有令人讨厌的细节。如果他需要区分浏览器中的静态C++实现,web开发人员会说什么?