Как соединить java и javascript
Перейти к содержимому

Как соединить java и javascript

  • автор:

Java & JavaScript: принципы и приемы взаимодействия

Рассматриваемые в этой статье возможности подразумевают использование в качестве броузера Netscape Navigator 3.0 или выше. Предполагается, что читатели владеют основами JavaScript и Java.

Известно, что языки JavaScript и Java расширяют возможности представления и обмена информацией на Ваших web-страницах. Но есть ограничения, которые накладываются при использовании этих языков. Вот несколько из них:

Для JavaScript

  1. Поле деятельности жестко ограничивается рамками броузера: все, что существует за его пределами, для JavaScript не существует вовсе. Обмен информацией с внешним миром возможен только при использовании различных HTML-расширений серверов (единого стандарта для которых нет вовсе), CGI и переменной location.search (Решение)
  2. Почти никаких функций для работы с изображениями (за исключением смены картинки в документе при помощи поля src объекта Image) (Решение)
  3. Интерфейс (за исключением форм) статичен и негибок (Решение)
  1. Отсутствует возможность динамической генерации документов (Решение)
  2. Отсутствует поддержка E-Mail (если не установлены специальные библиотеки, распространяемые отдельно от JDK) (Решение)
  3. До сих пор не решена проблема отображения символов русского алфавита (если не используется СУБД) (Решение)

Но. Можно заметить, что эти ограничения, накладываемые на один из языков, так или иначе обходятся в другом. Таким образом, обеспечив взаимодействие JavaScript-кода с Java-апплетами, можно еще более повысить гибкость Ваших страниц. В этой статье кратко описывается, как это делается, и даются примеры.

Для того, чтобы разрешить взаимодействие JavaScript и Java, Вам необходимо включить опции Enable Java и Enable JavaScript в меню Options|Network Preferences. |Languages.

Взаимодействие JavaScript и Java-апплетов может осуществляться тремя способами:

  • Доступ из JavaScript к переменным, методам, классам и пакетам Java
  • Управление Java-апплетами и внедренными объектами (plug-ins)
  • Доступ из Java-апплетов к методам и свойствам JavaScript

Классы пакета netscape:

Доступ из JavaScript к переменным, методам, классам и пакетам Java

Для доступа к классам и пакетам Java в JavaScript есть объект Packages . Используя свойства этого объекта, можно получить доступ к любому классу любого пакета, поддерживаемого навигатором. Напр., для доступа к пакетам java , sun и netscape используются следующие операторы: Packages.java , Packages.sun , Packages.netscape . Строго говоря, при обращении к этим трем пакетам использование Packages необязательно, чего нельзя сказать об остальных пакетах. Так, Packages.java.lang.System.out.println(myString) эквивалентно java.lang.System.out.println(myString) .

Нажав на кнопку, можно увидеть все переменные и методы вновь созданного объекта (внимание! нажатие на гиперссылку в создаваемом документе успешно выполнит только те методы, которые не принимают параметров (почему, видно из кода выше)):

Внимание! Не используйте любые методы Java, которые могут бросать исключения, т.к. в JavaScript нет обработки исключений, и код, вызывающий такие методы, не пройдет: будет выведено соответствующее сообщение

Управление Java-апплетами и внедренными объектами

Для обращения к Java-апплетам в документе можно использовать один из трех путей:

  • Обращение по имени апплета (указанному в параметре NAME тэга APPLET):
    document.appletName
  • Обращение по индексу в массиве applets:
    document.applets[index]
  • Обращение по имени апплета в качестве индекса в массиве applets:
    document.applets[«appletName»]

Напр., если в документе присутствует единственный апплет:

  • var aplt = document.myapplet
  • var aplt = document.applets[0]
  • var aplt = document.applets[«myapplet»]

После получения ссылки на апплет можно получить доступ к любым общедоступным (public) переменным и методам этого апплета.

  • Исходный текст апплета:
  • Фрагмент HTML-кода:

Нажатие на кнопку вызовет установку текста в апплете равным вычисленному выражению в поле ввода формы.

Внедренные объекты

Внедренные объекты (аудио- и видеофайлы WAV, AU, AVI. ) вставляются в документ при помощи тэга EMBED (должен быть установлен соответствующий plug-in). Синтаксис:

Здесь URL — URL внедряемого объекта. Параметры widthValue и heightValue — размер панели для размещения объекта. Используйте размеры 140 и 60 соответственно для полного показа панели и 2 и 2 для скрытия панели. (Установка размеров в 1×1 или 0x0 в действительности не принесет желаемого результата). Использование параметра NAME не рекомендуется, т.к. при этом часто блокируется работа внедренного объекта (скорее всего, это ошибка в раелизации Netscape Navigator 3.0) autostart=booleanValue — при загрузке объекта он сразу воспроизводится (действительно только для объектов, которые можно воспроизводить)
loop=booleanValue — при true воспроизведение пойдет по циклу (до покидания документа или вызове метода stop

Доступ к внедренным объектам осуществляется при помощи массива document.embeds[index] , где в качестве index следует указать индекс объекта (0 соответствует первому внедренному объекту, 1 — второму, . , document.embeds,length — 1 — последнему).

Чаще всего внедренный объект порождается от класса netscape.plugin.Plugin . В этом случае Вы можете использовать общедоступные переменные и методы данного класса для управления объектом. Кроме этого, каждый тип внедренного объекта может иметь свои собственные переменные и методы. Следующий код позволяет узнать, какие из них доступны в конкретном случае:

Общими для всех внедренных объектов являются следующие методы:

  • getWindow() — возвращает окно, содержащее документ, в который внедрен данный объект
  • isActive() — определяет, является ли данный объект активным в данный момент
  • Plugin() — конструктор

Остальные, не указанные здесь, методы используются в основном разработчиками новых внедряемых объектов (plug-ins). Вы не должны их вызывать.
Кроме этого, наиболее часто в объектах присутствуют три метода, которые обеспечивают основные функции управления:
play() — воспроизводит клип (если он таковым является) (при задании в качестве параметра функции true воспроизведение происходит в режиме LOOP)
stop() — останавливает воспроизведение, «перематывая» клип в начало
pause() — приостанавливает воспроизведение. После этого при вызове play() воспроизведение продолжится с того места, где было приостановлено

Доступ из Java-апплетов к методам и свойствам JavaScript

Для того, чтобы разрешить Java-апплетам доступ к методам и свойствам JavaScript, необходимо в тэге APPLET указать атрибут MAYSCRIPT, иначе будет бросаться исключение. Для доступа к JavaScript необходимо импортировать пакет Netscape javascript:

При этом в переменную окружения CLASSPATH необходимо добавить путь к файлу с пакетами, поставляемыми с Netscape Navigator. Напр., если Netscape Navigator установлен в каталог c:\Program Files\Navigator , в CLASSPATH необходимо добавить (для Netscape Navigator Gold) c:\Program Files\Navigator\Program\Java\CLASSES\java_301

Пакет javascript определяет класс JSObject для описания объектов JavaScript и исключение JSException, бросаемое при ошибке во время обращения к объектам JavaScript.

Перед тем, как Вы сможете получить доступ к JavaScript, Вам необходимо получить ссылку на окно (объект window), содержащее апплет:

Лучше всего включить этот оператор в функцию init() апплета.

Получить доступ к объектам и свойствам JavaScript можно одним из следующих способов:

  • Применив функцию eval объекта window:
  • Использовать метод getMember объекта JSObject для доступа к свойствам объектов JavaScript:

Вызвать методы объектов JavaScript можно одним из следующих способов:

  • Применив функцию eval :
  • Применив функцию call(«methodName», argumentsArray) объекта JSObject:

Данный способ позволяет вызвать не только методы объекта JavaScript, но и определенные пользователем функции (для чего используйте функцию call объекта winddow). Если функция/метод не принимает параметры, в качестве второго параметра функции call указывается пустой массив:

Преобразование типов от Java к JavaScript:

  • Java-типы byte, char, short, int, long, float и double преобразуются в числа JavaScript
  • Java-тип boolean преобразуется в boolean JavaScript
  • Java-тип JSObject преобразуется в соответствующий объект JavaScript
  • Прочие Java-объекты преобразуются в объекты-надстройки JavaScript для доступа к полям и методам этих объектов. Java-объекты могут быть преобразованы в строку (вызывается метод Java-объекта toString ). Если происходит преобразование в число, вызывается метод Java-объекта floatValue (который бросит исключение, если такое преобразование невозможно). Аналогично происходит преобразование в boolean (метод booleanValue )
  • Java-массивы преобразуются в псевдо-массивы JavaScript (которые в действительности ведут себя точно так же, как и JavaScript-массивы, где в качестве индекса используются целые числа, но устроены по другому)

Преобразование типов от JavaScript к Java:

  • Объекты-надстройки для Java-объектов преобразуются в Java-объекты
  • Остальные объекты преобразуются в JSObject
  • Строки, числа и boolean преобразуются соответственно в Java-объекты String, Float и Boolean

JSObject — объект JavaScript

Любой объект JavaScript в Java-апплетах представляется потомком класса JSObject (подробнее см. Доступ из Java-апплетов к методам и свойствам JavaScript)

Методы класса JSObject :

вызывает метод methodName объекта JavaScript с аргументами args[] . Эквивалентен JavaScript-коду:

вычисляет выражение s , являющееся любым допустимым выражением JavaScript. Вычисление производится в контексте объекта. Напр., код

в переменную doc занесет JavaScript-объект document

возвращает поле-член JavaScript-объекта. Аналогичен JavaScript-коду this.name . Напр., код

в переменную doc занесет JavaScript-объект document

Возвращает индексированный элемент массива (если объект им является). Аналогичен JavaScript-коду this[index] . Напр., код

в переменную frame1 занесет первую (т.е. с индексом 0) рамку окна

Возвращает JavaScript объект-окно, в котором выполняется апплет. Рекомендуется вызывать первым при взаимодействии с JavaScript

Удаляет поле-член JavaScript-объекта с именем name

Устанавливает значение поля-члена с именем name в value . Эквивалентен JavaScript-коду this.name = value

Устанавливает значение индексированного элемента с индексом index в value . Аналогичен JavaScript-коду this[index] = value

Преобразует объект JSObject в String

JavaScript: обмен информацией с внешним миром

Как известно, Java-апплеты могут обмениваться информацией с тем сервером, откуда он загружен, а если создать соответствующее серверное приложение, то через него и с любым сервером. (Очень хороший пример такого приложения — IDS Server компании IDS Software, взаимодействующий с апплетами с помощью пакетов ids.sql и с серверами или локальными базами данных через систему псевдонимов). Для того, чтобы код JavaScript мог воспользоваться такими возможностями, достаточно в апплете опреденить public-функцию, осуществляющую необходимый способ обмена информацией. После этого JavaScript вызывает данную функцию апплета, когда нужно.

JavaScript: работа с графикой

С помощью Java можно рисовать как на поверхности визуальных компонентов, так и на поверхности изображений (класс Image). Рисование происходит посредством объекта Graphics, являющегося одним из свойств класса Image. Из JavaScript можно напрямую вызывать функции объекта Graphics, предварительно создав в апплете public-переменную:

Таким же образом осуществляется рисование на поверхности компонентов апплета.

JavaScript: гибкий интерфейс

Обычно для поддержки взаимодействия с пользователями бывает достаточно использовать формы. Однако часто бывают ситуации, когда возможностей, предоставляемых формами, недостаточно. К тому же в случаях, когда во взаимодействии участвуют несколько HTML-документов (при большом числе вводимых параметров и необходимости динамически изменять последовательность действий), пользователям приходится много времени ждать загрузки тех или иных документов или блоков информации. Все это решается достаточно тривиально с использованием апплетов: хотя апплеты загружаются дольше обычных компонентов документа, это происходит один раз за сессию работы с броузером, а потом работают достаточно быстро. При этом можно создать один документ и все взаимодействие сосредоточить в нем.

Например, если количество вводимых параметров велико, можно установить для апплета (или какой-либо его панели) менеджер компоновки CardLayout и размещать интерфейсные элементы на его страницах (что является аналогом диалоговых окон в виде блокнота с закладками в Windows).

Если же необходимо динамически изменять последовательность действий и/или интерфейсные элементы, то делается это еще проще. В апплетах для изменения набора выводимых элементов предназначены такие функции класса Container, как void remove(Component comp) (для удаления из контейнера элемента comp), void removeAll() (для удаления из контейнера всех элементов) и Component add(Component comp [, int index]) (для добавления нового элемента). И связанная с этим последовательность действий легко изменяется.

Java: динамическая генерация документов

Часто бавает необходимо из Java-апплетов влиять на внешний вид документа в зависимости от некоторых условий (такие условия могут возникнуть в то время, когда документ уже загружен). Например, нужно создать какую-либо таблицу в ответ на введенные пользователем данные. Если контакт апплет загружен с СУБД-сервера, последний может (но не всегда) предоставить некоторые функции для динамической генерации документов. К сожалению, набор таких функций очень ограничен и неудовлетворителен. В других случаях дела обстоят еще сложнее. Таким образом, мы можем в апплете воспользоваться возможностями JavaScript в области создания документов. Для этого есть функция document.write(. ). Грамотно используя данную функцию можно построить документ (почти) любой сложности на лету.

Java: поддержка E-Mail

Из JavaScript есть возможности послать сообщение по E-Mail. Есть для этого три способа:

  1. Открывается стандартное окно ввода и отправки сообщения при щелчке на ссылке. Решение для Java-апплетов (если в документе есть ссылка наподобие <A HREF=»mailto:rbravant@yahoo.com» NAME=myMail>Send me</A> ): Если в тексте ссылки ничего не указать, то ее не будет видно на экране, но она будет функционировать.
  2. Вызывается функция click() кнопки submit формы, в которой в качестве action установлен E-Mail адрес (например, все тот же mailto:rbravant@yahoo.com). Решение для Java-апплетов:
  3. Открывается стандартное окно ввода и отправки сообщения при присваивании location.href значения E-Mail адреса. Решение для Java-апплетов:

Java: проблема символов русского алфавита

На самом деле существуют особые механизмы, которые позволяют работать с кириллицей несмотря на то, что в Java такая поддержка отсутствует. Они достаточно нетривиальны, и их рассмотрение выходит за рамки обсуждаемой темы. Есть легкий путь с применением JavaScipt вывода кириллицы в апплете. (Текст, введенный в апплет, может также успешно быть отправлен на сервер, хотя никакой гарантии в этом нет.) Решение таково: в документе в секции SCRIPT определяется ряд переменных с текстом на русском языке (не забудьте защитить символы я и ч обратным слэшем). Получить к ним доступ из апплета не составит труда.

Глава 14
LiveConnect. Обзор.

В этой главе рассматривается использование технологии LiveConnect для взаимодействия кодов, написанных на Java и JavaScript. Предполагается, что Вы уже знакомы с программированием на Java.

В главе имеются следующие разделы:

  • Что Такое LiveConnect?
  • Работа с Оболочками
  • Взаимодействие JavaScript с Java
  • Взаимодействие Java с JavaScript
  • Конвертация Типов Данных

Дополнительно об использовании LiveConnect см. JavaScript technical notes на сайте DevEdge, а также ищите соответствующую информацию на сайтах mozilla.org и developer.netscape.com.

Что Такое LiveConnect?

LiveConnect даёт возможность подключать приложения серверного JavaScript к Java-компонентам и классам на сервере.

Вашему приложению JavaScript может понадобиться соединиться с кодом, написанным на других языках, таких как Java или C. Для подключения к Java-коду Вы используете функциональность LiveConnect. Для взаимодействия с кодом, написанным на других языках, у Вас есть несколько вариантов:

  • Вы можете обернуть/wrap Ваш код как Java-объект и использовать LiveConnect непосредственно.
  • Вы можете обернуть Ваш код как распределённый объект CORBA и использовать LiveConnect совместно с object request broker (ORB).
  • Вы можете напрямую включать внешние библиотеки в Ваше приложение.

В этой главе обсуждается использование LiveConnect для доступа к не-JavaScript коду из приложений JavaScript.

Наконец, LiveConnect даёт возможность объектам JavaScript Вашего приложения взаимодействовать с Java-объектами. Эти Java-объекты являются экземплярами классов в серверном CLASSPATH . Об установке CLASSPATH см. книгу Programmer’s Guide to Servlets. LiveConnect работает и с клиентским, и серверным JavaScript, но имеет для каждой среды разные возможности.

Предполагается, что Вы уже знакомы с программированием на Java. Об использовании Java с Netscape-серверами см. Enterprise Server 3.5.1/3.6: Notes for Java Programmers 1 . О LiveConnect см. DevEdge Library 2 .

Во всех доступных Java-классах Вы можете иметь доступ к статичным public-свойствам или методам или создавать экземпляры класса и получать доступ к public-свойствам и методам этих экземпляров. В отличие от клиентского, однако, Вы можете иметь доступ только к тем Java-объектам, которые были созданы Вашим приложением или другим приложением JavaScript, а затем сохранены как свойство объекта server .

Если Java-объект был создан серверным приложением, отличным от приложения на серверном JavaScript, Вы не можете иметь доступ к этому Java-объекту.
Например, Вы не можете получить доступ к Java-объекту, созданному WAI plug-in, расширением NSAPI или HTTP-аплетом.

Когда Вы вызываете метод Java-объекта, Вы можете передать объекты JavaScript в этот метод. Код Java может установить свойства и вызвать методы этих объектов JavaScript. Таким образом, Вы можете иметь и код JavaScript, вызывающий код Java, и код Java, вызывающий код JavaScript.

Код Java может иметь доступ к приложению JavaScript только таким способом. То есть Java-объект не может вызывать приложение JavaScript, если это приложение JavaScript (или другое приложение JavaScript) не имеет само доступа к соответствующему Java-объекту и не вызывает один из его методов.

Работа с Оболочками

В JavaScript wrapper\оболочка это объект типа данных целевого языка, который содержит в себе объект исходного языка. На стороне JavaScript Вы можете использовать объект-оболочку для доступа к методам и полям Java-объекта; вызывая метод или получая доступ к свойству в оболочке даёт в результате вызов Java-объекта. На стороне Java объекты JavaScript оборачиваются в экземпляры класса netscape.javascript.JSObject и передаются в Java.

Когда JavaScript-объект высылается в Java, машина выполнения создаёт Java-оболочку типа JSObject ; когда JSObject высылается из Java в JavaScript, машина выполнения разворачивает его в объект оригинального типа JavaScript. Класс JSObject предоставляет интерфейс для вызова методов JavaScript и проверки свойств JavaScript.

Взаимодействие JavaScript с Java

Когда Вы обращаетесь к пакету или классу Java или работаете с объектом или массивом Java, Вы используете один из специальных объектов LiveConnect. Доступ JavaScript к Java имеет место в объектах, резюме по которым дано в следующей таблице.

Таблица 14.1 Объекты LiveConnect

Обёрнутый/wrapped массив Java, доступ к которому выполняется в коде JavaScript.

Взаимодействие Java и JavaScript с помощью LiveConnect

LiveConnect – это метод, позволяющий Java и JavaScript взаимодействовать друг с другом. Это позволяет вашему классу Java вызывать методы JavaScript и обращаться к среде JavaScript. JavaScript также может обращаться к объектам Java и вызывать методы для них. LiveConnect впервые был реализован в браузере Netscape, и в настоящее время Mozilla Firefox полностью поддерживает эту функцию. В этом руководстве вы узнаете, как писать код, который делает возможным взаимодействие между Java и JavaScript.

Существует два основных аспекта LiveConnect:

  • Вызов методов Java из JavaScript
  • Использование объектов JavaScript в Java

Доступ к Java из JavaScript:

Всякий раз, когда вам нужен доступ к Java-объекту, классу, массиву или пакету, просто используйте один из следующих четырех объектов LiveConnect.

  • JavaObject – используется для доступа к объекту Java из JavaScript.
  • JavaClass – используется как ссылка на класс Java.
  • JavaArray – используется для доступа к массивам Java.
  • JavaPackage – используется как ссылка на пакет Java.

Использование JavaObject

Вы можете создать объект Java и назначить его переменной в JavaScript с помощью new ключевого слова. Когда вы создаете экземпляр класса Java, JavaScript автоматически создает объект JavaObject . Например, вы можете создать экземпляр Java String из JavaScript и назначить его переменной. Затем вы можете использовать оператор точки для доступа к методу length() объекта, как показано ниже.

Использование JavaClass

Всякий раз, когда вы ссылаетесь на класс Java в своем коде и назначаете его переменной, среда выполнения JavaScript автоматически создает объект JavaClass . Например, следующий код создает объект JavaClass .

Использование JavaPackage

Точно так же, когда ваш код JavaScript ссылается на пакет Java, среда выполнения JavaScript автоматически создает объект JavaPackage . В этом случае мы создаем экземпляр класса MyClass который находится внутри пакета mypackage .

Если ваш класс не является частью какого-либо пакета, его можно напрямую создать, как показано в следующем примере.

Обычно используемые классы, такие как классы в пакетах java , sun и netscape могут быть созданы следующим образом.

Приведенный выше код эквивалентен следующему:

Использование JavaArray

Объекты JavaArray создаются автоматически при каждом создании массива Java внутри кода JavaScript. Например, следующий код создает массив Java, содержащий пять String .

Позже вы можете распечатать длину массива, используя свойство length .

Доступ к объектам JavaScript внутри кода Java

В основном мы используем следующие два класса для доступа к среде JavaScript из Java.

  • netscape.javascript.JSObject – Используется для доступа к методам и свойствам JavaScript.
  • netscape.javascript.JSException – Используется для обработки исключений в коде Java.

Эти классы не доступны для вашего кода по умолчанию. Чтобы сделать их доступными, вам нужно добавить jar, содержащий эти классы, в ваш CLASSPATH . Откройте каталог установки JRE и перейдите в папку lib . Вы найдете файл jar с именем plugin.jar . Добавьте этот jar в путь к классам, чтобы два вышеупомянутых класса были доступны для JRE во время работы приложения.

Использование JSObject

Все объекты JavaScript, которые появляются в Java, имеют тип JSObject . Помните, мы говорили о вызове методов Java из JavaScript? Ну, вы можете вызвать любой метод Java из кода JavaScript и передать объекты JavaScript в метод в качестве параметра. Эти объекты затем преобразуются в тип JSObject на стороне Java. Чтобы эти методы работали, вам нужно определить формальные параметры типа JSObject в сигнатуре метода Java. В следующем примере показано, как Java-класс Player получает JSObject через конструктор и использует его для получения членов объекта JavaScript.

Далее мы создадим объект с именем Player в JavaScript.

Теперь можно создать объект Player JavaScript и передать его конструктору класса Java Player при его создании.

Использование JSException для обработки ошибок JavaScript в Java

Все может пойти не так в вашем коде Java при доступе к среде JavaScript. В этом случае на JSException приходит класс JSException . В следующем примере демонстрируется использование JSException .

Пример использования

Теперь, когда мы знаем, как вызывать методы Java из JavaScript и использовать объекты JavaScript внутри Java, пришло время создать небольшое приложение, чтобы общая концепция была понятна. Мы создадим очень простое приложение, которое попросит пользователя ввести его / ее имя, возраст и язык программирования по выбору. В зависимости от выбранного языка, приложение отобразит сообщение с указанием наилучшей основы для изучения. Поскольку мы используем LiveConnect для сборки приложения, у нас есть класс Programmer на Java и JavaScript.

На странице также есть апплет. Это сделано потому, что самый первый объект, доступный для LiveConnect, является экземпляром общедоступного апплета. Из апплета мы можем получить желаемый объект. В нашей программе LauncherApplet имеет метод, который возвращает объект Programmer . Во-первых, нам нужно вызвать этот метод, чтобы получить экземпляр Programmer в нашем коде JavaScript. Основная идея заключается в предварительном заполнении объекта Programmer . Затем, после загрузки HTML-страницы, покажите сообщение, отображающее различные свойства объекта. Затем возьмите пользовательский ввод из формы HTML и создайте объект JavaScript Programmer .

Следующим шагом является передача вновь созданного объекта JavaScript в метод Java setData . Метод Java считывает свойства объекта и обновляет его свойства. Убедитесь, что класс Programmer объявлен как открытый, иначе вы не сможете получить к нему доступ из JavaScript. В качестве последнего шага мы вызываем другой метод getAdvice() для объекта Java, который возвращает персонализированный совет о том, какую среду должен использовать пользователь.

Исходный код для класса Java Programmer показан ниже.

Наш класс LauncherApplet выглядит следующим образом:

Структура нашей HTML-страницы следующая:

В liveconnect.js мы определяем две функции и один класс Programmer . Класс Programmer определен ниже.

Далее мы определяем функцию showProgrammer() , которая показывает свойства Java-объекта Programmer при загрузке страницы. Код для функции приведен ниже:

Наконец, мы определяем processProgrammer() которая считывает processProgrammer() имя, возраст и язык программирования. Затем он использует эти значения для создания объекта JavaScript Programmer и вызывает setData() на стороне Java. Объект JavaScript Programmer является аргументом для setData() . На следующем шаге мы используем свойства объекта Java Programmer для подготовки рекомендаций. Наконец, совет возвращается в сторону JavaScript.

Вывод

Подключив JavaScript к Java, вы можете создавать очень мощные приложения. Однако LiveConnect не полностью поддерживается всеми браузерами. Вышеупомянутое приложение протестировано в Firefox 11.0, а код Java скомпилирован с использованием JDK 7. Поэтому, если вы хотите протестировать примеры кода, убедитесь, что в вашей системе установлен JDK 7. Чтобы узнать больше о LiveConnect, посетите LiveConnect в сети разработчиков Mozilla .

3 Using Java From Scripts

This chapter describes how to access Java classes and interfaces from scripts.

The code snippets are written in JavaScript, but you can use any scripting language compliant with JSR 223. Examples can be used as script files, or can be run in an interactive shell one expression at a time. The syntax for accessing fields and methods of objects is the same in JavaScript as it is in Java.

This chapter contains the following sections:

3.1 Accessing Java Classes

To access primitive and reference Java types from JavaScript, call the Java.type() function, which returns a type object that corresponds to the full name of the class passed in as a string. The following example shows you how to get various type objects:

The type object returned by the Java.type() function can be used in JavaScript code similar to how a class name is used in Java. For example, you can can use it to instantiate new objects as follows:

Java type objects can be used to instantiate new Java objects. The following example shows you how to instantiate new objects using the default constructor and by passing arguments to another constructor:

You can use the type object returned by the Java.type() function to access static fields and methods as follows:

To access a static inner class, use the dollar sign ($) in the argument passed to the Java.type() method. The following example shows how to return the type object of the Float inner class in java.awt.geom.Arc2D :

If you already have the outer class type object, then you can access the inner class as a property of the outer class as follows:

In case of a nonstatic inner class, you must pass an instance of the outer class as the first argument to the constructor.

Although a type object in JavaScript is used similar to the Java class, it is distinct from the java.lang.Class object, which is returned by the getClass() method. You can obtain one from the other using the class and static properties. The following example shows this distinction:

Syntactically and semantically, this distinction between compile-time class expressions and runtime class objects makes JavaScript similar to Java code. However, there is no equivalent of the static property for a Class object in Java, because compile-time class expressions are never expressed as objects.

3.2 Importing Java Packages and Classes

To access Java classes by their simple names, you can use the importPackage() and importClass() functions to import Java packages and classes. These functions are built into the compatibility script ( mozilla_compat.js ). The following example shows you how to use the importPackage() and importClass() functions:

You can access Java packages using the Packages global variable (for example, Packages.java.util.Vector or Packages.javax.swing.JFrame ), but standard Java SE packages have shortcuts ( java for Packages.java , javax for Packages.javax , and org for Packages.org ).

The java.lang package is not imported by default, because its classes would conflict with Object , Boolean , Math , and other built-in JavaScript objects. Furthermore, importing any Java package or class can lead to conflicts with the global variable scope in JavaScript. To avoid this, define a JavaImporter object and use the with statement to limit the scope of the imported Java packages and classes, as shown in the following example:

3.3 Using Java Arrays

To create a Java array object, you first have to get the Java array type object, and then instantiate it. The syntax for accessing array elements and the length property in JavaScript is the same as in Java, as shown in the following example:

Given a JavaScript array, you can convert it to a Java array using the Java.to() method. You must pass the JavaScript array variable to this method and the type of array to be returned, either as a string or a type object. You can also omit the array type argument to return an Object[] array. Conversion is performed according to the ECMAScript conversion rules. The following example shows you how to convert a JavaScript array to a Java array using various Java.to() method arguments:

Given a Java array, you can convert it to a JavaScript array using the Java.from() method. The following example shows you how to convert a Java array that contains a list of files in the current directory to a JavaScript array with the same contents:

3.4 Implementing Java Interfaces

The syntax for implementing a Java interface in JavaScript is similar to how anonymous classes are declared in Java. You instantiate an interface and implement its methods (as JavaScript functions) in the same expression. The following example shows you how to implement the Runnable interface:

If a method expects an object that implements an interface with only one method, you can pass a script function to this method instead of the object. For instance, in the previous example, the Thread() constructor expects an object that implements the Runnable interface, which defines only one method. You can take advantage of automatic conversion and pass a script function to the Thread() constructor instead of the object. The following example shows you how you can create a Thread object without implementing the Runnable interface:

You can implement multiple interfaces in a subclass by passing the relevant type objects to the Java.extend() function. For more information, see Extending Concrete Java Classes.

3.5 Extending Abstract Java Classes

You can instantiate an anonymous subclass of an abstract Java class by passing to its constructor a JavaScript object with properties whose values are functions that implement the abstract methods. If a method is overloaded, then the JavaScript function will provide implementations for all variants of the method. The following example shows you how to instantiate a subclass of the abstract TimerTask class:

Instead of invoking the constructor and passing an argument to it, you can provide the argument directly after the new expression. The following example shows you how this syntax (similar to Java anonymous inner class definition) can simplify the second line in the previous example:

If the abstract class has a single abstract method (a SAM type), then instead of passing a JavaScript object to the constructor, you can pass the function that implements the method. The following example shows how you can simplify the syntax when using a SAM type:

Whichever syntax you choose, if you need to invoke a constructor with arguments, you can specify the arguments after the implementation object or function.

If you want to invoke a Java method that takes a SAM type as the argument, you can pass a JavaScript function to the method. Nashorn will instantiate a subclass of the expected class and use the function to implement its only abstract method. The following example shows you how to invoke the Timer.schedule() method, which expects a TimerTask object as the argument:

3.6 Extending Concrete Java Classes

To avoid ambiguity, the syntax for extending abstract classes is not allowed for concrete classes. Because a concrete class can be instantiated, such syntax may be interpreted as an attempt to create a new instance of the class and pass to it an object of the type expected by the constructor (in case when the expected object type is an interface). As an illustration of this, consider the following example:

This code can be interpreted both as extending the Thread class with the specified implementation of the run() method, and the instantiation of the Thread class by passing to its constructor an object that implenents the Runnable interface (for more information, see Implementing Java Interfaces).

To extend a concrete Java class, pass its type object to the Java.extend() function that returns a type object of the subclass. Then, use the type object of the subclass as a JavaScript-to-Java adapter to create instances of the subclass with the specified method implementations. The following example shows you how to extend the Thread class with the specified implementation of the run() method:

The Java.extend() function can take a list of multiple type objects. You can specify no more than one type object of a Java class, and as many type objects of Java interfaces as you want. The returned type object extends the specified class (or java.lang.Object if no class is specified) and implements all interfaces. The class type object does not have to be first in the list.

3.7 Accessing Methods of a Superclass

To access methods in the superclass, you can use the Java.super() function. Example 3-1 shows you how to extend the java.lang.Exception class and access the methods in the superclass.

Example 3-1 Accessing Methods of a Supreclass (super.js)

If you run the code in Example 3-1, the following will be printed to standard output:

3.8 Binding Implementations to Classes

The previous sections described how to extend Java classes and implement interfaces using an extra JavaScript object parameter in the constructor that specifies the implementation. The implementation is therefore bound to the actual instance created with new , and not to the whole class. This has some advantages, for example, in the memory footprint of the runtime, because Nashorn can create a single universal adapter for every combination of types being implemented. However, the following example shows that different instances have the same Java class regardless of them having different JavaScript implementation objects:

The previous example prints the following:

If you want to pass the class for instantiation to an external API (for example, when using the JavaFX framework, the Application class is passed to the JavaFX API, which instantiates it), you must extend a Java class or implement an interface with the implementation bound to the class, rather than to its instances. You can bind the implementation to the class by passing a JavaScript object with the implementation as the last argument to the Java.extend() function. This creates a class with the same constructors as the original class, because they do not need an extra implementation object parameter. The following example shows you how to bind implementations to the class, and demonstrates that in this case the implementation classes for different invocations are different:

The previous example prints the following:

Moving the implementation objects from the constructor invocations to the invocations of the Java.extend() functions eliminates the need for an extra argument in the constructor invocations. Every invocation of the Java.extend() function with a class-specific implementation object produces a new Java adapter class.The adapter classes with class-bound implementations can still take an additional constructor argument to further override the behavior for certain instances. Thus, you can combine the two approaches: you can provide part of the implementation in a class-based JavaScript implementation object passed to the Java.extend() function, and provide implementations for instances in objects passed to the constructor. A function defined by the object passed to the constructer overrides the function defined by the class-bound object. The following example shows you how to override the function defined in the class-bound object with a function passed to the constructor:

The previous example prints the following:

3.9 Selecting Method Overload Variant

Java methods can be overloaded by argument types. The Java Compiler ( javac ) selects the correct method variant during compilation. Overload resolution for Java methods called from Nashorn is performed when the method is invoked. The correct variant is selected automatically based on the argument types. However, if you run into genuine ambiguity with actual argument types, you can specify a particular overload variant explicitly. This may also improve performance, because the Nashorn engine will not need to perform overload resolution during invocation.

Overload variants are exposed as special properties. You can refer to them in the form of strings that contain the name of the method followed by the argument types within parantheses. The following example shows how to invoke the variant of the System.out.println() method that expects an Object class as the argument, and pass «hello» to it:

In the previous example, the unqualified class name ( Object ) is sufficient, because it uniquely identifies the correct signature. The only case when you must use the fully qualified class names in the signature is when two overload variants use different parameter types with identical unqualified names (this is possible if parameter types with the same name are from different packages).

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Объект Описание