Prefácio
Todo o código deste artigo está escrito no JavaScript, mas você também pode usar outras linguagens de script compatíveis com 223 JSR. Esses exemplos podem ser executados como arquivos de script ou em conchas interativas executando uma instrução por vez. A sintaxe para acessar propriedades e métodos de objetos em JavaScript é a mesma da linguagem Java.
Este artigo contém as seguintes partes:
1. Acesse aulas de Java
Para acessar tipos nativos ou referenciar tipos Java em JavaScript, você pode chamar a função Java.type() , que retorna o tipo do objeto correspondente com base no nome de classe completa. O código a seguir mostra como obter diferentes tipos de objetos:
var ArrayList = java.type ("java.util.arraylist"); var inttype = java.type ("int"); var stringArrayType = java.type ("java.lang.string []; O método de retornar um objeto de tipo usando Java.type() no JavaScript é semelhante ao do Java.
Por exemplo, você pode instanciar uma classe usando o seguinte método:
var anarraylist = new java.type ("java.util.arraylist");Objetos do tipo Java podem ser usados para instanciar objetos Java. O código a seguir mostra como instanciar um novo objeto usando o construtor padrão e chamar o construtor que contém os parâmetros:
var ArrayList = java.type ("java.util.ArrayList"); var defaultSizearrayList = new ArrayList; var alfabearsizearRayList = new ArrayList (16); Você pode usar Java.type() para obter o tipo de objeto e pode usar os seguintes métodos para acessar propriedades e métodos estáticos:
var arquivo = java.type ("java.io.file"); file.createTempfile ("Nashorn", ".tmp"); Se você deseja acessar a classe estática interna, pode passar o sinal de dólar $ para Java.type() .
O código a seguir mostra como devolver Float de java.awt.geom.Arc2D :
var float = java.type ("java.awt.geom.arc2d $ float");Se você já possui um objeto de tipo de classe externo, pode acessar sua classe interna, assim como acessaria a propriedade, como mostrado abaixo:
var arc2d = java.type ("java.awt.geom.arc2d") var float = arc2d.floatComo é uma classe interna não estática, a instância da classe externa deve ser passada como um parâmetro para o construtor.
Embora o uso de objetos de tipo em JavaScript seja semelhante ao do Java, ele ainda é um pouco diferente do objeto java.lang.Class . Essa diferença é o valor de retorno do método getClass() . Você pode usar class e as propriedades static para obter essas informações.
O código a seguir mostra a diferença entre os dois:
var ArrayList = java.type ("java.util.ArrayList"); var a = new ArrayList; // Todos os seguintes são verdadeiros: print ("O tipo atua como alvo de instância:" + (não é a instância A.Cet); + (a.getclass ()! == ArrayList)); print ("A propriedade` class` do tipo é a mesma da instância getClass (): " + (a.getclass () === ArrayList.class)); Print) (" Tipo é o mesmo que a propriedade `static` da instância getClass ():" + (A.Sintaxe e semântica, expressões de classe JavaScript e objetos de tempo de execução são semelhantes à semântica Java. No entanto, em Java, o objeto de classe não possui uma propriedade chamada estática porque a expressão de classe compilada não é usada como objeto.
2. Importar pacotes e classes Java
Para acessar as classes Java com base em seu nome simples, podemos usar importPackage() e importClass() para importar pacotes e classes Java. Essas funções existem no arquivo de script de compatibilidade (mozilla_compat.js).
O exemplo a seguir mostra como usar importPackage() e importClass() :
// Carregar scriptload de compatibilidade ("Nashorn: mozilla_compat.js"); // importe o java.awt packageImportPackage (java.awt); // importar o java.awt.frame classimportclass (java.awt.frame); setVisible () MethodFrame.SetVisible (true); // Acesse um Javabean PropertyPrint (Frame.title); Os pacotes Java podem ser acessados através da variável global dos pacotes, como Packages.java.util.Vector ou Packages.javax.swing.JFrame . No entanto, o pacote Java SE padrão possui métodos de acesso mais simples, como: java corresponde a pacotes.java, javax corresponde a packages.javax e org corresponde a packages.org.
O pacote java.lang não requer importação por padrão, porque isso entrará em conflito com outros objetos internos JavaScript, como Object , Boolean e Math . Além disso, a importação de pacotes e classes Java também pode causar conflitos de nomes variáveis sob o escopo global do JavaScript. Para evitar conflitos, definimos um objeto Javaimporter e limitamos o escopo dos pacotes e classes Java importados através with , conforme mostrado no código a seguir:
// cria um objeto Javaimporter com pacotes e classes especificados para importar gui = new javaimporter (java.awt, javax.swing); // Pass o objeto Javaimporter para a declaração "com" com as classes e acessar as classes // a partir dos pacotes importados por seus nomes simples no corpo (awith "(gi) {vari awr aw; var jframe = new jframe ("swing jframe");};3. Use matrizes Java
Para criar um objeto Java Array, primeiro você precisa obter o objeto do tipo Java Array e inicializá -lo. O atributo de sintaxe e length do acesso a JavaScript aos elementos da matriz são os mesmos que Java, conforme mostrado no código a seguir:
var stringArray = java.type ("java.lang.string []"); var a = new StringArray (5); // Defina o valor das primeiras elementos [0] = "Script é ótimo!"; // imprima o comprimento do ArrayPrint (a.length); // imprimir o valor do primeiro elemento (a 0]; Dada uma matriz JavaScript, também podemos convertê -la em uma matriz Java usando Java.to() . Precisamos passar a matriz JavaScript como um parâmetro para o método e especificar o tipo da matriz a ser retornada, que pode ser uma string ou um objeto de tipo. Também podemos ignorar os parâmetros do objeto de tipo para retornar a matriz do objeto []. A operação de conversão é realizada de acordo com as regras de conversão do ECMAScript. O código a seguir mostra como transformar uma matriz JavaScript em uma matriz Java através de diferentes parâmetros Java.to() :
// Crie uma matriz JavaScript var anarray = [1, "13", false]; // converte uma matriz em java int [] matriz var javaintary = java.to (anarray, "int []"); print (javaintary [0]); // imprime o número 1PRINT (JavaintArray [1]); // imprime o número 13Print (JavaintArray [2]); // imprime o número 0 // Converta JavaScript Array em javastringArray = java.to (anarray, java.type ("java.lang.string []")); print (javastringArray [0]); // imprime a string "1" print (javastringArray [1]); // imprime a string "13" Print (javastringArray [2]); // imprime a string "false" // Converte JavaScript Array em Java Object [] Array var javaobjectArray = java.to (anarray); print (javaobjectArray [0]); // imprime o número 1PRINT (JavaObjectArray [1]); // imprime a string "13" print (javaobjectArray [2]); // imprime o valor booleano "false" Você pode usar Java.from() para converter uma matriz Java em uma matriz JavaScript.
O código a seguir mostra como converter uma matriz que contém a lista de arquivos no diretório atual em uma matriz JavaScript:
// Obtenha o arquivo Java Type Objectvar File = java.type ("java.io.file"); // Crie uma matriz java de arquivo objeto listcurdir = new file ("."). Listfiles (); // convert the java Array para um listurcript Arrayvar JsList = java. java.from (JavuriScript ArrayVar Jsist = java. java.from para um JavurScript ArrayVar ArrayPrint (JSLIST);Perceber:
Na maioria dos casos, você pode usar objetos Java em seu script sem convertê -los em objetos JavaScript.
4. Implementar a interface Java
A sintaxe da implementação de interfaces Java em JavaScript é semelhante ao método de definir classes anônimas em Java. Só precisamos instanciar a interface e implementar seus métodos com funções JavaScript.
O código a seguir demonstra como implementar a interface Runnable :
// Crie um objeto que implementa a interface executável implementando // o método run () como um javascript functionVar r = new java.lang.runnable () {run: function () {print ("em execução .../n"); }}; // A variável R pode ser passada para os métodos java que esperam um objeto que implemente // java.lang.runnable interfacevar th = new java.lang.thread (r); th.start (); th.join (); Se um método deseja um objeto, esse objeto implementa uma interface com apenas um método, você pode passar uma função de script para esse método em vez de passar o objeto. Por exemplo, no exemplo acima, Thread() requer um objeto que implementa Runnable como um parâmetro. Podemos aproveitar a conversão automática para passar uma função de script para o construtor Thread() .
O exemplo a seguir mostra como criar um objeto Thread sem implementar uma interface Runnable :
// Defina uma função de função JavaScript func () {print ("Eu sou func!");}; // Pass pela função JavaScript em vez de um objeto que implementa // java.lang.runnable interfaceVar th = new java.lang.thread (func); th.start (); Você pode implementar várias interfaces passando objetos de tipo relacionado para Java.extend() .
5. Extendo as classes abstratas de java
Você pode instanciar uma subclasse de classe abstrata anônima, basta passar um objeto JavaScript para o construtor, que contém algumas propriedades correspondentes aos valores implementados pelo método da classe abstrata. Se um método estiver sobrecarregado, a função JavaScript fornecerá implementações de todas as variantes de método. O exemplo a seguir mostra como inicializar uma subclasse da classe abstrata TimerTask:
var timerTask = java.type ("java.util.timertak"); var tarefa = new TimerTask ({run: function () {print ("hello world!")}}); Além de chamar o construtor e passar parâmetros, também podemos fornecer parâmetros diretamente após a new expressão.
O exemplo a seguir mostra como usar essa sintaxe (semelhante à definição de classes internas anônimas em Java), que é um pouco mais simples que o exemplo acima:
var tarefa = new TimerTask {run: function () {print ("Hello World!")}};Se a classe abstrata contiver um único método abstrato (tipo SAM), não precisamos passar por um objeto JavaScript para o construtor, podemos passar uma interface de função que implementa o método. O exemplo a seguir mostra como usar os tipos SAM para simplificar o código:
var tarefa = new TimerTask (function () {print ("Hello World!")});Independentemente da sintaxe que você escolher, se você precisar chamar um construtor que contém parâmetros, poderá especificar parâmetros no objeto e na função de implementação.
Se você deseja chamar um método Java que requer parâmetros do tipo SAM, pode passar uma função JavaScript para o método. Nashorn instanciará uma subclasse de acordo com as necessidades do método e usará essa função para implementar o método abstrato exclusivo.
O código a seguir mostra como chamar Timer.schedule() , que requer um objeto Timertosk como um parâmetro:
var timer = java.type ("java.util.timer"); timer.schedule (function () {print ("hello world!")});Perceber:
A sintaxe anterior assume que o tipo SAM necessário é uma interface ou contém um construtor padrão, que Nashorn usa para inicializar uma subclasse. Isso não é possível usar uma classe que não contenha o construtor padrão.
6. Estenda as classes java específicas
Para evitar confusão, a sintaxe para estender classes abstratas não pode ser usada para estender as classes de concreto. Como uma classe de concreto pode ser instanciada, essa sintaxe é analisada na tentativa de criar uma nova instância de classe e passar o objeto da classe exigida pelo construtor (se o tipo de objeto esperado for uma interface). Para demonstrar esse problema, dê uma olhada no seguinte código de exemplo:
var t = new java.lang.thread ({run: function () {print ("Thread Running!")}}); Essa linha de código é analisada para estender a classe Thread e implementar run() , e a instanciação Thread é passada ao seu construtor um objeto que implementa a interface executável.
Para estender uma classe de concreto, passe seu objeto de tipo para a função Java.extend() e retorne seu objeto de tipo à sua subclasse. Em seguida, você pode usar o objeto Tipo desta subclasse para criar instâncias e fornecer implementações de métodos adicionais.
O código a seguir mostrará como estender Thread e implementar run() :
var thread = java.type ("java.lang.thread"); var threadExtender = java.extend (thread); var t = new ThreadExtender () {run: function () {print ("Thread em execução!")}}; Java.extend() pode obter uma lista de vários tipos de objetos. Você pode especificar não mais que um objeto do tipo java ou especificar o número de objetos de tipo até as interfaces java. O objeto de tipo retornado estende a classe especificada (ou java.lang.Object , se não houver objeto de tipo especificado), esta classe implementa todas as interfaces. Os objetos de tipo da classe não precisam estar na parte superior da lista.
7. Métodos para acessar a Superclass (classe pai)
Os métodos que desejam acessar a classe pai podem usar a função Java .super() .
O exemplo a seguir mostra como estender java.lang.Exception e acessar os métodos da classe pai.
Exemplo 3-1 Método para acessar a classe pai (super.js) var excepção = java.type ("java.lang.exception"); var excepcionAdapter = java.extend (excepção); var excepcionalmente = novo excepcionário ("minha mensagem de exceção") {getMessage: function () {var _super_ = java.sper ") return _super_.getMessage (). touppercase (); }} tente {throw Exception;} catch (ex) {print (excepção);}Se você executar o código acima, imprimirá o seguinte:
jdk.nashorn.javaadapters.java.lang.exception: minha mensagem de exceção
8. Ligação para implementar à classe
Na seção anterior, descrevemos como estender as classes Java e implementar a interface usando um parâmetro de objeto JavaScript adicional. A implementação está vinculada a uma instância específica, que é criada através de novas, não por toda a classe. Existem alguns benefícios em fazer isso, como a pegada de memória em tempo de execução, pois Nashorn pode criar um único adaptador universal para a combinação de tipos de cada implementação.
O exemplo a seguir mostra que diferentes instâncias podem ser a mesma classe Java, mas seus objetos de implementação de JavaScript são diferentes:
var runnable = java.lang.runnable; var r1 = new Runnable (function () {print ("I'm Runnable 1!")}); var r2 = new Runnable (function () {Print ("I'm Runnable 2!")}); r1.run (); r2.run (); ""O código acima imprimirá o seguinte resultado:
Eu estou executado 1! Estou executado 2! Compartilhamos a mesma classe: verdadeiro
Se você deseja passar uma instância de uma classe para uma API externa (como a estrutura Javafx, passando uma instância de aplicativo para a API Javafx), você deve estender uma classe Java ou implementar uma interface ligada a essa classe, em vez de sua instância. Você pode implementar a classe passando uma ligação de objeto JavaScript e passando -a para o último parâmetro da função java.extend (). Isso cria uma nova classe com o mesmo construtor que a classe original, porque eles não requerem implementação adicional de parâmetros de objeto.
O exemplo a seguir mostra como vincular uma implementação a uma classe e demonstra que as classes de implementação são diferentes para chamadas diferentes neste caso:
var runnableImpl1 = java.extend (java.lang.runnable, function () {print ("I'm Runnable 1!")}); var runnableImpl2 = java.Extend (java.lang.Runnable, function ("Print (" I'm Runnable 2! "); RunnableImpl2 (); r1.run (); r2.run (); print ("Compartilhamos a mesma classe:" + (r1.class === r2.class));Os resultados de execução do exemplo acima são os seguintes:
Eu estou executado 1! Estou correndo 2! Compartilhamos a mesma classe: false
Mover o objeto de implementação da chamada do construtor para Java.extend() evita os parâmetros extras necessários na chamada do construtor. Cada chamada para Java.extend() requer um objeto de implementação da classe especificada para gerar uma nova classe de adaptador Java. As classes adaptadoras implementadas com os limites da classe ainda podem usar um parâmetro de construtor adicional para substituir ainda mais o comportamento de uma instância específica. Assim, você pode mesclar esses dois métodos: você pode fornecer parte da implementação do JavaScript em uma classe base, depois passá -la para a função Java.extend() e fornecer uma implementação de instância no objeto e passá -lo para o construtor. Algumas definições de função do objeto serão substituídas quando o objeto for definido e passado para o construtor.
O código a seguir demonstra como substituir uma função de um objeto de limite de classe, passando uma função para o construtor:
var runnableImpl = java.extend (java.lang.runnable, function () {print ("I'm Runnable 1!")}); var r1 = new runnableImpl (); var r2 = new runnableImpl (function () {Print ("I'm Runnable 2!")}); (r1.class === r2.class));Os resultados da impressão após a execução do exemplo acima são os seguintes:
Eu estou executado 1! Estou executado 2! Compartilhamos a mesma classe: verdadeiro
9. Selecione a variante de sobrecarga do método
Os métodos Java podem ser sobrecarregados usando diferentes tipos de parâmetros. O compilador Java (JAVAC) selecionará o método correto para executar no momento da compilação. A análise dos métodos sobrecarregados de Java em Nashorn é executada quando o método é chamado. É também uma maneira de determinar o método correto com base no tipo de parâmetro. Mas se o tipo de parâmetro real causar ambiguidade, podemos especificar explicitamente uma variante sobrecarregada específica. Isso melhora o desempenho da execução do programa, porque o mecanismo Nashorn não precisa distinguir qual método chamar durante a chamada.
As variantes sobrecarregadas são expostas como propriedades especiais. Podemos nos referir a eles na forma de cordas, que contêm nomes de métodos e tipos de parâmetros e estão cercados por parênteses.
O exemplo a seguir mostra como chamar System.out.println() com Object , passamos uma string "Hello" para ele:
var out = java.lang.system.out; out ["println (object)"] ("hello");No exemplo acima, o uso do nome da classe de objeto é suficiente porque é a assinatura que identifica exclusivamente a correta. O caso em que você deve usar o nome completo da classe é que duas funções de variantes sobrecarregadas usam diferentes tipos de parâmetros, mas o tipo tem o mesmo nome (isso é possível, por exemplo, pacotes diferentes contêm o mesmo nome de classe).
10. Tipos de dados de mapeamento
A grande maioria das conversões anteriores Java e JavaScript funciona bem como você esperaria. Nos capítulos anteriores, mencionamos alguns mapeamentos simples de tipo de dados entre Java e JavaScript. Por exemplo, os dados do tipo de matriz podem ser explicitamente convertidos, as funções JavaScript podem ser convertidas automaticamente aos tipos de SAM quando passadas como parâmetros para os métodos Java. Cada objeto JavaScript implementa a interface java.util.Map para permitir que a API aceite diretamente os mapeamentos. Ao passar valores para a API Java, eles serão convertidos para o tipo numérico de destino esperado, que pode ser um tipo de encapsulamento ou um tipo de dados primitivo. Se o tipo de destino não for muito certo (como número), você poderá exigir apenas que seja o tipo de número e, em seguida, encapsular especificamente o tipo, como duplo, número inteiro, longo, etc. Otimização interna torna o valor numérico de qualquer tipo de pacote. Colegas, você pode passar qualquer valor JavaScript para a API Java, seja um tipo encapsulado ou um tipo primitivo, porque o algoritmo de conversão ToNumber do JavaScript processará automaticamente seu valor. Se um método Java requer uma String ou parâmetro de objeto Boolean , o JavaScript usará transformações ToString e ToBoolean para obter seu valor.
Perceber:
Devido às considerações internas de otimização de desempenho para operações de string, as cadeias de javascript nem sempre correspondem ao tipo java.lang.string, ou também podem ser java.lang.CharSequence . Se você passa uma sequência JavaScript para um método Java que requer o parâmetro java.lang.String , a sequência JavaScript é o tipo java.lang.String , mas se a assinatura do seu método deseja ser mais genérica (por exemplo, o objeto de que o objeto é que o objeto não é o que o objeto, o objeto não é o que o objeto, o objeto, o objeto, o objeto, o objeto, o objeto, que o objeto, o objeto de que o objeto não é que o objeto não é que o objeto não é o que é CharSequence , o objeto de que é um parâmetro.
Resumir
O acima é o conteúdo inteiro deste artigo. Espero que seja de ajuda para estudar e trabalhar de todos. Se você tiver alguma dúvida, pode deixar uma mensagem para se comunicar.