Достъп до статични Java променливи от js код в Nashorn engine

Докато се опитвах да пренеса стар код, работещ с Rhino engine към Nashorn в Java 8, получих проблема, статични свойства/методи не могат да бъдат достъпни от изпълняващ js скрипт. Ако използвам Rhino, работи перфектно. Не знам какво се случва с внедряването на новия двигател на Nashorn.

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

person truongdao    schedule 20.09.2015    source източник


Отговори (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.

person Attila Szegedi    schedule 20.09.2015
comment
Работи! просто има нужда от някои промени в кода. Между другото, тези методи не са обратно съвместими с Rhino. Благодаря! - person truongdao; 20.09.2015

Това не е начинът, по който js трябва да работи. Мисля, че това е дизайнерска грешка в Nashorn. Да приемем, че имате смесена програма, предаваща променливи от някаква система за изпълнение на Java към js скрипта. Този обект съдържа един статичен метод fmtNumber(someString) и един обектен метод jutil.getFormVar(someString). Потребителите не трябва да знаят, че Java обслужва тази платформа. Просто им казвате, че jutil е "системна кука", принадлежаща на рамката foo. Като потребител на тази рамка не ме интересува дали е статична или не. Аз съм js разработчик, не знам за static или не. Искам да напиша нещо много бързо. Ето как изглежда кодът в rhino.

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

Сега в nashorn трябва да ги разгранича. Дори по-лошо, аз дори трябва да обучавам потребителите си да правят разлика между тях и да ги уча на термини на Java, които те може да не знаят, защото това е, което представлява абстракционният слой: самостоятелна система без необходимост да познават основните механизми. Това разграничение е начин за много когнитивно претоварване и вие не сте мислили за други случаи на използване освен за разработчиците на Java, които изпълняват скриптове за себе си, което вероятно няма да го направят, защото вече знаят добър език, наречен Java. Вие мислите от внедряването си като Java разработчик, когато вместо това трябва да мислите как бихте могли да използвате силата на Java Plattform във фонов режим, скривайки всички неприятни подробности от JS разработчиците. Какво би казал един уеб разработчик, ако трябва да прави разлика между статичното внедряване на C++ в браузъра?

person Christoph Sauer    schedule 04.02.2016