从Nashorn引擎中的js代码访问静态Java变量

时间:2015-09-20 05:02:20

标签: rhino static-variables nashorn

在尝试将运行Rhino引擎的旧代码移植到Java 8中的Nashorn时,我遇到了麻烦,无法通过运行js脚本访问静态属性/方法。如果我使用Rhino,它运行得很好。我不知道新Nashorn引擎的实现会发生什么。

import java.util.Scanner;
class case2 {
   public static void main(String args[]) {
   Scanner entry = new Scanner(System.in);
   int a, b;
   int i;

do {
   System.out.println("Main Menu :");
   System.out.println("1.   Plus");
   System.out.println("2.   Minus");
   System.out.println("3.   Multiply");
   System.out.println("4.   Division");
   System.out.println("5.   Exit");
   System.out.println("Option :");

    i = entry.nextInt(); 
    System.out.println(" ");  

    switch(i) {
       case 1 :
         System.out.println("Menu 1 :");
         System.out.print("Var A :");
         a = entry.nextInt();
         System.out.print("Var B :");
         b = entry.nextInt();
         System.out.println("Result :" + (a+b));
         if(a>b) {
           System.out.println(a +" > "+b);
         }
         else if(a<b) {
           System.out.println(a +" < "+b);
         }
         else {
           System.out.println(a +" = "+b);
         }
         System.out.println("*press any key back to menu*");

         break;
       case 2 :
         System.out.println("Menu 2 :");
         System.out.print("Var A :");
         a = entry.nextInt();
         System.out.print("Var B :");
         b = entry.nextInt();
         System.out.println("Result :" + (a-b));
         if(a>b) {
           System.out.println(a +" > "+b);
         }
         else if(a<b) {
           System.out.println(a +" < "+b);
         }
         else {
           System.out.println(a +" = "+b);
         }
         System.out.println("*press any key back to menu*");

         break;
       case 3 :
         System.out.println("Menu 3 :");
         System.out.print("Var A :");
         a = entry.nextInt();
         System.out.print("Var B :");
         b = entry.nextInt();
         System.out.println("Result :" + (a*b));
         if(a>b) {
           System.out.println(a +" > "+b);
         }
         else if(a<b) {
           System.out.println(a +" < "+b);
         }
         else {
           System.out.println(a +" = "+b);
         }
         System.out.println("*press any key back to menu*");

         break;

       case 4 :
         System.out.println("Menu 4 :");
         System.out.print("Var A :");
         a = entry.nextInt();
         System.out.print("Var B :");
         b = entry.nextInt();
         System.out.println("Result :" + (a/b));
         if(a>b) {
           System.out.println(a +" > "+b);
         }
         else if(a<b) {
           System.out.println(a +" < "+b);
         }
         else {
           System.out.println(a +" = "+b);
         }
         System.out.println("*press any key back to menu*");

         break;
           case 5:
                 break;
     default:
         System.out.println("ERROR");
         System.out.println("*press any key back to menu*");        



        }
  }while(i != 5);


  }
}

2 个答案:

答案 0 :(得分: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平台习语。

答案 1 :(得分:0)

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

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

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