머리말
이 기사의 모든 코드는 JavaScript로 작성되었지만 다른 JSR 223 호환 스크립팅 언어를 사용할 수도 있습니다. 이 예제는 한 번에 하나의 명령문을 실행하여 스크립트 파일 또는 대화식 쉘로 실행할 수 있습니다. JavaScript의 객체의 속성 및 방법에 액세스하기위한 구문은 Java 언어와 동일합니다.
이 기사에는 다음 부분이 포함되어 있습니다.
1. Java 클래스에 액세스하십시오
JavaScript에서 기본 유형 또는 참조 Java 유형에 액세스하려면 Java.type() 함수를 호출 할 수 있으며, 이는 전체 클래스 이름으로 전달 된 것을 기준으로 해당 객체의 유형을 반환합니다. 다음 코드는 다른 객체 유형을 얻는 방법을 보여줍니다.
var arraylist = java.type ( "java.util.arraylist"); var inttype = java.type ( "int"); var stringarraytype = java.type ( "java.lang.string []); var int2darraytype = java.type ("[]]); Java.type() 함수를 사용하여 유형 객체를 반환하는 방법은 Java와 유사합니다.
예를 들어 다음 방법을 사용하여 클래스를 인스턴스화 할 수 있습니다.
var anarraylist = new java.type ( "java.util.arraylist");
Java 유형 객체는 Java 객체를 인스턴스화하는 데 사용될 수 있습니다. 다음 코드는 기본 생성자를 사용하여 새 개체를 인스턴스화하는 방법을 보여주고 매개 변수를 포함하는 생성자를 호출하는 방법을 보여줍니다.
var arraylist = java.type ( "java.util.arraylist"); var defaultsizearraylist = new arraylist; var customsizearraylist = new arraylist (16);
Java.type() 메소드를 사용하여 객체 유형을 얻을 수 있으며 다음 방법을 사용하여 정적 특성 및 메소드에 액세스 할 수 있습니다.
var file = java.type ( "java.io.file"); file.createtempfile ( "Nashorn", ".tmp");
내부 정적 클래스에 액세스하려면 Dollar Sign $를 Java.type() 메소드로 전달할 수 있습니다.
다음 코드는 Float 내부 클래스의 java.awt.geom.Arc2D 반환하는 방법을 보여줍니다.
var float = java.type ( "java.awt.geom.arc2d $ float");
외부 클래스 유형 객체가 이미있는 경우 아래와 같이 속성에 액세스하는 것처럼 내부 클래스에 액세스 할 수 있습니다.
var arc2d = java.type ( "java.awt.geom.arc2d") var float = arc2d.float
비 정적 내부 클래스이므로 외부 클래스 인스턴스는 생성자에게 매개 변수로 전달되어야합니다.
JavaScript에서 유형 객체를 사용하는 것은 Java와 유사하지만 java.lang.Class 객체와는 여전히 다릅니다. 이 차이는 getClass() 메소드의 반환 값입니다. class 및 static 속성을 사용 하여이 정보를 얻을 수 있습니다.
다음 코드는 두 가지의 차이를 보여줍니다.
var arraylist = java.type ( "java.util.arraylist"); var a = new arraylist; // 다음은 모두 사실입니다 : "인스턴스의 대상으로 작용합니다 :" + (instanceof arraylist)); print ( " +! (A.GetClass ()) ("타입 ()); ") + (a.getClass ()! == arraylist)); print ( "type 's`class'속성은 인스턴스의 getClass ()와 동일합니다.구문 및 의미론, JavaScript 클래스 표현식 및 런타임 개체는 Java Semantics와 유사합니다. 그러나 Java에서는 클래스 객체에 컴파일 된 클래스 표현식이 객체로 사용되지 않기 때문에 Class 객체에는 static이라는 속성이 없습니다.
2. Java 패키지 및 클래스 수입
간단한 이름을 기반으로 Java 클래스에 액세스하려면 importPackage() 및 importClass() 함수를 사용하여 Java 패키지 및 클래스를 가져올 수 있습니다. 이러한 기능은 호환성 스크립트 파일 (Mozilla_compat.js)에 존재합니다.
다음 예제는 importPackage() 및 importClass() 함수 사용 방법을 보여줍니다.
// 호환성 스크립트로드 ( "Nashorn : Mozilla_compat.js"); // java.awt packageimportpackage (java.awt); // java.awt.frame classimportclass (java.awt.frame); // aver java.awt.frame (hello (hello) "; setVisible () methodframe.setvisible (true); // javabean propertyprint (frame.title)에 액세스합니다.
Java 패키지는 Packages.java.util.Vector 또는 Packages.javax.swing.JFrame 과 같은 패키지 글로벌 변수를 통해 액세스 할 수 있습니다. 그러나 표준 Java SE 패키지는 다음과 같은 더 간단한 액세스 방법을 가지고 있습니다.
java.lang 패키지는 기본적으로 가져 오기가 필요하지 않습니다. 이는 Object , Boolean 및 Math 와 같은 다른 JavaScript 내장 객체와 충돌하기 때문입니다. 또한 Java 패키지 및 클래스를 가져 오면 JavaScript의 글로벌 범위에 따라 가변 이름 충돌이 발생할 수 있습니다. 충돌을 피하기 위해 Javaimporter 객체를 정의하고 다음 코드에 표시된대로 with 통해 가져온 Java 패키지 및 클래스의 범위를 제한합니다.
// importVar gui = new javaimporter (java.awt, javax.swing)로 지정된 패키지 및 클래스가있는 javaimporter 객체를 만듭니다. // javaimporter 객체를 "문의"명령문으로 전달하고 문장의 신체 와이드 (GUI) 내의 간단한 이름으로 수입 된 패키지에 액세스하십시오. var jframe = new Jframe ( "스윙 Jframe");};
3. Java 어레이를 사용하십시오
Java 배열 객체를 만들려면 먼저 Java 배열 유형 객체를 얻고 초기화해야합니다. 배열 요소에 대한 JavaScript 액세스의 구문 및 length 속성은 다음 코드와 같이 Java와 동일합니다.
var stringArray = java.type ( "java.lang.string []"); var a = new StringArray (5); // 첫 번째 요소의 값을 설정하십시오 [0] = "스크립팅은 훌륭합니다!"; // ArrayPrint의 길이 (a.length); // 첫 번째 요소의 값을 인쇄합니다 (A [0]);
JavaScript 배열이 주어지면 Java.to() 메소드를 사용하여 Java 배열로 변환 할 수도 있습니다. JavaScript 배열을 메소드에 매개 변수로 전달하고 리턴 할 배열의 유형을 지정해야합니다. 이는 문자열 또는 유형 객체 일 수 있습니다. 객체 [] 배열을 반환하기 위해 유형 객체 매개 변수를 무시할 수도 있습니다. 전환 작업은 ECMAScript 변환 규칙에 따라 수행됩니다. 다음 코드는 Java.to() 매개 변수를 통해 JavaScript 배열을 Java 배열로 전환하는 방법을 보여줍니다.
// JavaScript 배열 생성 var anarray = [1, "13", false]; // 배열을 java int [] 배열 var javaintarray = java.to (anarray, "int []"; print (javaintarray [0])로 변환합니다. // 숫자 1print (javaintarray [1])를 인쇄합니다. // 숫자 13print (javaintarray [2])를 인쇄합니다. // 숫자 0을 인쇄 // JavaScript 배열을 JavastringArray = java.to (anarray, java.type ( "java.lang.string []"); print (javastringarray [0])로 변환합니다. // 문자열 "1"print (javastringArray [1])를 인쇄합니다. // 문자열 "13"print (javastringArray [2])를 인쇄합니다. // 문자열 "false"// javaScript 배열 변환 java 객체 [] 배열 var var javaobjectarray = java.to (anarray); print (javaobjectarray [0]); // 숫자 1print (javaobjectarray [1])를 인쇄합니다. // 문자열 "13"print (javaobjectarray [2])를 인쇄합니다. // 부울 가치 "false"인쇄
Java.from() 메소드를 사용하여 Java 배열을 JavaScript 배열로 변환 할 수 있습니다.
다음 코드는 현재 디렉토리의 파일 목록을 포함하는 배열을 JavaScript 배열로 변환하는 방법을 보여줍니다.
// java 파일 유형 객체 파일을 가져옵니다. ArrayPrint (jslist);
알아채다:
대부분의 경우 JavaScript 객체로 변환하지 않고 스크립트에서 Java 객체를 사용할 수 있습니다.
4. Java 인터페이스 구현
JavaScript에서 Java 인터페이스를 구현하는 구문은 Java에서 익명 클래스를 정의하는 방법과 유사합니다. 인터페이스를 인스턴스화하고 JavaScript 기능으로 메소드를 구현하면됩니다.
다음 코드는 Runnable 인터페이스를 구현하는 방법을 보여줍니다.
// javaScript functionvar r = new java.lang.runnable () {function () {print ( "running .../n"); }}; // r 변수는 java.lang.runnable interfacevar th = new java.lang.thread (r); th.start (); th.join (); 메소드가 객체를 원한다면이 객체는 하나의 메소드만으로 인터페이스를 구현하면 객체를 전달하는 대신 스크립트 함수를이 메소드로 전달할 수 있습니다. 예를 들어, 위의 예에서, Thread() 생성자는 Runnable 인터페이스를 매개 변수로 구현하는 객체가 필요합니다. 자동 변환을 활용하여 스크립트 함수를 Thread() 생성자로 전달할 수 있습니다.
다음 예제는 Runnable 인터페이스를 구현하지 않고 Thread 객체를 만드는 방법을 보여줍니다.
// javaScript functionFunction function function func () {print ( "i am func!");}; // // java.lang.runnable interfacevar th = new java.lang.thread (func); th.start (); th.join (); 관련 유형 객체를 Java.extend() 함수로 전달하여 여러 인터페이스를 구현할 수 있습니다.
5. 초록 Java 클래스를 확장하십시오
익명의 추상 클래스 서브 클래스를 인스턴스화하고 JavaScript 객체를 생성자에게 전달할 수 있습니다. 여기에는 Abstract 클래스 메소드에 의해 구현 된 값에 해당하는 일부 속성이 포함되어 있습니다. 메소드가 과부하되면 JavaScript 함수는 모든 메소드 변형의 구현을 제공합니다. 다음 예제는 추상 클래스 타이머 스탁의 서브 클래스를 초기화하는 방법을 보여줍니다.
var timertask = java.type ( "java.util.timertask"); var task = new Timertask ({run : function () {print ( "Hello World!")}); 생성자를 호출하고 매개 변수를 전달하는 것 외에도 new 표현식 직후에 파라미터를 제공 할 수도 있습니다.
다음 예제는이 구문을 사용하는 방법을 보여줍니다 (Java의 익명 내부 클래스의 정의와 유사). 위의 예보다 약간 간단합니다.
var task = new Timertask {run : function () {print ( "Hello World!")}};초록 클래스에 단일 추상 메소드 (SAM 유형)가 포함 된 경우 JavaScript 객체를 생성자에게 전달할 필요가 없으므로 메소드를 구현하는 기능 인터페이스를 전달할 수 있습니다. 다음 예제는 SAM 유형을 사용하여 코드를 단순화하는 방법을 보여줍니다.
var task = new Timertask (function () {print ( "Hello World!")});선택한 구문에 관계없이 매개 변수가 포함 된 생성자를 호출 해야하는 경우 구현 객체 및 기능에 매개 변수를 지정할 수 있습니다.
Sam 유형 매개 변수가 필요한 Java 메소드를 호출하려면 JavaScript 함수를 메소드에 전달할 수 있습니다. Nashorn은 방법 요구에 따라 서브 클래스를 인스턴스화 하고이 기능을 사용하여 고유 한 추상 방법을 구현합니다.
다음 코드는 Timer.schedule() 메소드를 호출하는 방법을 보여줍니다.이 방법은 Timertask 객체가 매개 변수로 필요합니다.
var timer = java.type ( "java.util.timer"); timer.schedule (function () {print ( "Hello World!")});알아채다:
이전 구문은 필요한 SAM 유형이 인터페이스 또는 기본 생성자를 포함한다고 가정합니다. Nashorn은 서브 클래스를 초기화하는 데 사용합니다. 기본 생성자가 포함되지 않은 클래스를 사용할 수 없습니다.
6. 특정 Java 클래스를 확장하십시오
혼란을 피하기 위해 추상 클래스를 확장하기위한 구문을 사용하여 구체적인 클래스를 확장 할 수 없습니다. 구체적인 클래스를 인스턴스화 할 수 있기 때문에 이러한 구문은 새 클래스 인스턴스를 생성하고 생성자가 요구하는 클래스의 객체를 전달하려는 시도로 구문 분석됩니다 (예상 객체 유형이 인터페이스 인 경우). 이 문제를 입증하려면 다음 샘플 코드를 살펴보십시오.
var t = new java.lang.thread ({run : function () {print ( "스레드 실행!")}); 이 코드 라인은 Thread 클래스를 확장하고 run() 메소드를 구현하기 위해 구문 분석되며 Thread 클래스의 인스턴스화는 생성자에게 Runnable 인터페이스를 구현하는 객체로 전달됩니다.
콘크리트 클래스를 확장하려면 유형 객체를 Java.extend() 함수로 전달한 다음 유형 객체를 서브 클래스로 반환하십시오. 그런 다음이 서브 클래스의 유형 객체를 사용하여 인스턴스를 생성하고 추가 메소드 구현을 제공 할 수 있습니다.
다음 코드는 Thread 클래스를 확장하고 run() 메소드를 구현하는 방법을 보여줍니다.
var thread = java.type ( "java.lang.thread"); var threestendender = java.extend (스레드); var t = new restrextender () {run : function () {print ( "스레드 running!")}; Java.extend() 함수는 여러 유형의 객체 목록을 얻을 수 있습니다. 하나 이상의 Java 유형 객체를 지정하거나 Java 인터페이스만큼 유형 객체 수를 지정할 수 있습니다. 반환 된 유형 객체는 지정된 클래스 (또는 java.lang.Object , 지정된 유형 객체가없는 경우)를 확장하면이 클래스는 모든 인터페이스를 구현합니다. 클래스의 유형 객체는 목록의 맨 위에있을 필요가 없습니다.
7. 슈퍼 클래스에 액세스하는 방법 (부모 클래스)
상위 클래스에 액세스하려는 메소드는 Java .super() 함수를 사용할 수 있습니다.
다음 예제는 java.lang.Exception 클래스를 확장하고 부모 클래스의 메소드에 액세스하는 방법을 보여줍니다.
예 3-1 부모 클래스 (super.js) var exception = java.type ( "java.lang.exception"); var ExceptionAdapter = java.extend (예외); var exception = new ExceptionAdapter ( "내 예외 메시지") {getMessage : function () {var _super_ = java.super (예외); return _super_.getMessage (). touppercase (); }} try {Throw Exception;} catch (ex) {print (예외);}위의 코드를 실행하면 다음을 인쇄합니다.
jdk.nashorn.javaadapters.java.lang.exception : 예외 메시지
8. 클래스에 구현하기위한 바인딩
이전 섹션에서는 Java 클래스를 확장하고 추가 JavaScript 객체 매개 변수를 사용하여 인터페이스를 구현하는 방법을 설명했습니다. 구현은 특정 인스턴스에 바인딩되며 전체 클래스가 아닌 새로 생성됩니다. Nashorn은 각 구현의 유형 조합에 대해 단일 범용 어댑터를 만들 수 있기 때문에 런타임시 메모리 풋 프린트와 같이이를 수행하는 데 몇 가지 이점이 있습니다.
다음 예는 다른 인스턴스가 동일한 Java 클래스 일 수 있지만 JavaScript 구현 객체는 다르다는 것을 보여줍니다.
var runnable = java.lang.runnable; var r1 = new runnable (function () {print ( "ike runnable 1!")}); var r2 = new r2 = new Runnable ( "I 'm Runnable 2!"))위의 코드는 다음 결과를 인쇄합니다.
나는 달리기 가능 1!
클래스 인스턴스를 외부 API (예 : Javafx 프레임 워크, 응용 프로그램 인스턴스를 Javafx API에 전달)로 전달하려면 Java 클래스를 확장하거나 인스턴스가 아닌 해당 클래스에 제한된 인터페이스를 구현해야합니다. JavaScript 객체 바인딩을 전달하여 java.extend () 함수의 마지막 매개 변수로 전달하여 클래스를 구현할 수 있습니다. 이는 객체 매개 변수의 추가 구현이 필요하지 않기 때문에 원래 클래스와 동일한 생성자를 가진 새 클래스를 만듭니다.
다음 예제는 구현을 클래스에 바인딩하는 방법을 보여 주고이 경우 구현 클래스가 다릅니다.
var runnableimpl1 = java.extend (java.lang.runnable, function () {print ( "ike runnable 1!") {var runnableimpl2 = java.extend (java.lang.runnable, function () {print ( "I 'm runtable 2!") runnableimpl2 (); r1.run (); r2.run (); print ( "우리는 같은 클래스를 공유합니다 :" + (r1.class === r2.class));위의 예제 실행 결과는 다음과 같습니다.
나는 달리기 가능 1!
구현 객체를 생성자 호출에서 Java.extend() 함수 호출로 이동하면 생성자 호출에 필요한 추가 매개 변수를 피합니다. Java.extend() 함수에 대한 각 호출에는 새로운 Java 어댑터 클래스를 생성하기 위해 지정된 클래스의 구현 객체가 필요합니다. 클래스 경계와 함께 구현 된 어댑터 클래스는 여전히 추가 생성자 매개 변수를 사용하여 특정 인스턴스의 동작을 추가로 무시할 수 있습니다. 따라서이 두 가지 방법을 병합 할 수 있습니다. 기본 클래스에서 JavaScript 구현의 일부를 제공 한 다음 Java.extend() 함수로 전달하여 객체의 인스턴스 구현을 제공하여 생성자로 전달할 수 있습니다. 물체의 일부 기능 정의는 객체를 정의하고 생성자로 전달할 때 덮어 씁니다.
다음 코드는 기능을 생성자에게 전달하여 클래스 경계 객체의 함수를 덮어 쓰는 방법을 보여줍니다.
var runnableimpl = java.extend (java.lang.runnable, function () {print ( "ike runnable 1!")}; var r1 = new RunnableImpl (); var r2 = new RunnableImpl () {print ( "I 'm Runnable 2!")}; (r1.class === r2.class);위의 예제가 실행 된 후 인쇄 결과는 다음과 같습니다.
나는 달리기 가능 1!
9. 메소드 과부하 변형을 선택하십시오
다른 매개 변수 유형을 사용하여 Java 메소드를 과부하 할 수 있습니다. Java 컴파일러 (Javac)는 컴파일 시간에 실행할 올바른 방법을 선택합니다. Nashorn에서 Java 과부하 된 방법의 구문 분석은 메소드가 호출되면 실행됩니다. 또한 매개 변수 유형을 기반으로 올바른 방법을 결정하는 방법이기도합니다. 그러나 실제 매개 변수 유형이 모호성을 유발하는 경우 특정 과부하 된 변형을 명시 적으로 지정할 수 있습니다. Nashorn 엔진은 통화 중에 호출 할 방법을 구별 할 필요가 없기 때문에 프로그램 실행의 성능을 향상시킵니다.
과부하 된 변형은 특수 특성으로 노출됩니다. 방법 이름과 매개 변수 유형을 포함하고 괄호로 둘러싸인 문자열 형태로 참조 할 수 있습니다.
다음 예제는 Object 매개 변수 변형을 사용하여 System.out.println() 메소드를 호출하는 방법을 보여줍니다. "hello"문자열을 전달합니다.
var out = java.lang.system.out; out [ "println (Object)"] ( "Hello");
위의 예에서, 객체 클래스 이름 만 사용하면 올바른 이름을 고유하게 식별하는 서명이기 때문에 충분합니다. 전체 클래스 이름을 사용해야하는 경우 두 개의 오버로드 된 변형 기능이 다른 매개 변수 유형을 사용하지만 유형은 동일한 이름을 갖는 것입니다 (예 : 다른 패키지에는 동일한 클래스 이름이 포함되어 있음).
10. 데이터 유형 매핑
Java 및 JavaScript 이전 전환의 대다수는 예상대로 잘 작동합니다. 이전 장에서는 Java와 JavaScript 사이의 간단한 데이터 유형 매핑을 언급했습니다. 예를 들어, 배열 유형 데이터를 명시 적으로 변환 할 수 있으며, Java 메소드로 매개 변수로 전달 될 때 JavaScript 기능을 SAM 유형으로 자동 변환 할 수 있습니다. 각 javaScript 객체는 java.util.Map 인터페이스를 구현하여 API가 매핑을 직접 허용 할 수 있도록합니다. 값을 Java API로 전달할 때 예상 대상 숫자 유형으로 변환되며, 이는 캡슐화 유형 또는 기본 데이터 유형 일 수 있습니다. 대상 유형이 확실하지 않은 경우 (예 : 숫자), 숫자 유형이되도록 요구 한 다음 구체적으로 Double, Inter, Long 등과 같은 유형을 캡슐화 할 수 있습니다. 내부 최적화는 모든 패키지 유형의 숫자 값을 만듭니다. 동료, JavaScript의 ToNumber 변환 알고리즘이 자동으로 값을 처리하기 때문에 캡슐화 된 유형이든 원시 유형이든 Java API에 JavaScript 값을 Java API에 전달할 수 있습니다. Java 메소드에 String 또는 Boolean 객체 매개 변수가 필요한 경우 JavaScript는 ToString 및 ToBoolean 변환을 사용하여 그 값을 얻습니다.
알아채다:
문자열 작업에 대한 내부 성능 최적화 고려 사항으로 인해 JavaScript 문자열이 항상 java.lang.string 유형에 해당하는 것은 아니거나 java.lang.CharSequence 유형 일 수도 있습니다. java.lang.String 매개 변수가 필요한 Java 메소드로 Java 스크립트를 전달하는 경우 JavaScript 문자열은 java.lang.String 유형이지만 메소드 서명이 더 일반적인 것으로 원한다면 (예 : 허용되는 매개 변수 유형이 Java.lang.object), CharSequence )가 java 끈이 아닌 객체를 만들어냅니다.
요약
위는이 기사의 전체 내용입니다. 모든 사람의 연구와 일에 도움이되기를 바랍니다. 궁금한 점이 있으면 의사 소통을 위해 메시지를 남길 수 있습니다.