Привязка Java Integer к JavaScriptEngine не работает - PullRequest
2 голосов
/ 24 июня 2011

Чтобы увидеть, как работает привязка объектов Java к символам на динамическом языке, я написал следующий тест шипа , связывающий java.lang.Integer с символом i, который нужно изменить в JavaScript:

  @Test 
  public void bindToLocalVariable() throws ScriptException {

    javax.script.ScriptEngineManager sem 
       = new javax.script.ScriptEngineManager();
    javax.script.ScriptEngine engine 
       = sem.getEngineByName("JavaScript");    

    Integer i = new Integer(17);

    engine.put( "i", i );        
    engine.eval( "i++;" );  // Now execute JavaScript

    assertEquals( 18, i.intValue() );        

    }

К сожалению, я получаю ошибку.

java.lang.AssertionError: expected:<18> but was:<17>

JavaScript знает символ i (в противном случае он выбросил бы ScriptException, что не так), но операция приращения i++ не выполняется для исходного объекта Integer,

Есть объяснения?

Ответы [ 3 ]

1 голос
/ 24 июня 2011

Вот что происходит в вашем коде:

Integer i = new Integer(17);

Эта строка создает две вещи:

  • Локальная переменная типа Integer с именем i.
  • Новый Integer объект со значением 17.

Локальная переменная инициализируется ссылкой на вновь созданный объект Integer (т.е. теперь она указывает на объект Integer).

Объект Integer нельзя изменить, поскольку он неизменен.
Локальную переменную можно изменить, присвоив ей новую ссылку.

engine.put( "i", i );

Эта строка передает значение из i (которое является ссылкой на объект Integer) в метод put(). Это означает, что put только знает об объекте Integer и не о переменной i. А поскольку сам объект Integer нельзя изменить, не может повлиять на метод (или любой другой метод), чтобы повлиять на то, что хранится в локальной переменной i.

engine.eval( "i++;" );  // Now execute JavaScript

Этот метод эффективно обрабатывает переменную JavaScript i, созданную предыдущей строкой. Эта переменная была инициализирована со значением локальной переменной Java i, но это не то же самое, что локальная переменная .

assertEquals( 18, i.intValue() );      

Здесь вы проверяете значение локальной переменной Java i, которое не изменяется. только способ сделать это утверждение правильным, назначив что-то еще i (например, i = new Integer(18)).

1 голос
/ 24 июня 2011

Я не знаю JavaSrciptEngine, но Integer является неизменным, поэтому у вас все равно будет прежнее значение после его изменения в JavaScript.

Редактировать: убрать автобокс, чтобы сделать его более понятным:

Это очень похоже на это:

Integer i = new Integer(17);
Integer j = i;  //should be similar to the assignment in Javascript
j++; //the change to j is not reflected in i

System.out.println(i); //prints 17 not 18
0 голосов
/ 25 июня 2011

Спасибо Томасу и Йоахиму Зауэру за то, что они указали, что проблема была в неизменности java.lang.Integer.

Целое число отображается в подлинную переменную JavaScript с помощью engine.put() и может рассматриваться как число. Если вам нужен результат, позвоните engine.get(), чтобы передать его обратно в Java. Это отличается от примера List<String> в http://java.sun.com/developer/technicalArticles/J2SE/Desktop/scripting/, где объект Java передается в сценарий, и его собственные методы (как определено в Java) применяются к нему из сценария обратным вызовом в Java с использованием отражения.

Интересно отметить, что Integer будет извлечен из JavaScript как Double, указывая на то, что действительно имелось прямое и обратное сопоставление с объектом данных JavaScript.

Вот проходной тест (опуская экземпляр engine, который все тот же, что и в моем вопросе - тем временем я его извлек).

  @Test 
  public void bindToInteger() throws ScriptException {

    Integer i = 17;

    engine.put( "i", i );        
    engine.eval( "i++" );  // Execute JavaScript

  // i is mapped back to java.lang.Double by get()
    double f = (Double) engine.get("i");  
    assertEquals( 18,  (int) f );        

    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...