Java™ 访问函数是 EGL 系统函数,它们允许生成的 Java 代码访问本机 Java 对象和类;具体地说,允许 Java 代码访问本机代码的公用方法、构造函数和字段。
在运行时,由于存在 EGL Java 对象空间而使此 EGL 功能成为可能,其中,EGL Java 对象空间是一组名称以及那些名称所引用的对象。有一个对象空间可供生成的程序以及该程序以本地方式调用的所有 Java 生成代码使用,无论那些调用是直接的还是通过另一个本地 Java 生成程序进行的均如此,并且可用于任何级别的调用。此对象空间不能用在任何本机 Java 代码中。
要在对象空间中存储和检索对象,请调用 Java 访问函数。这些调用包括使用标识,每个标识都是用来存储对象或用来匹配对象空间中已存在的名称的字符串。当标识与名称相匹配时,代码就可以访问与该名称相关联的对象。
将把传递给方法的每个自变量(以及赋予字段的每个值)映射至 Java 对象或基本类型。例如,具有 EGL 基本类型 CHAR 的项是作为 Java 字符串类的对象传递的。提供了强制类型转换运算符来用于 EGL 类型到 Java 类型的映射并不充分的情况。
当您指定 Java 名称时,EGL 将从值的开头和末尾除去单字节和双字节空格,其中,值是区分大小写的。截断操作在任何强制类型转换之前发生。此规则适用于字符串文字以及类型为 CHAR、DBCHAR、MBCHAR 或 UNICODE 的项。除非将值强制类型转换为 objID 或 NULL,否则,在指定方法自变量或字段值时不会发生这种截断(例如,将字符串“ my data ”按原样传递给方法)。
下表描述了所有有效映射。
自变量的类别 | 示例 | Java 类型 | |
---|---|---|---|
字符串文字或类型为 CHAR、DBCHAR、 MBCHAR 或 UNICODE 的项 | 不进行强制类型转换 | "myString" |
java.lang.String |
使用 objId 进行强制类型转换,objId 指示了标识 | (objId)"myId" x = "myId"; (objId)X |
标识所引用的对象的类 | |
使用 NULL 进行强制类型转换,这可能适合于提供对标准类的空引用 | (null)"java. lang.Thread" x = "java.util. HashMap"; (null)x |
指定的类
注: 不能传入强制类型转换为 NULL 的数组,如 (null)"int[]"
|
|
使用 char 进行强制类型转换,这表示传递值的第一个字符(下一列中的每个示例都传递“a”) | (char)"abc" X = "abc"; (char)X |
char | |
类型为 FLOAT 的项或浮点文字 | 不进行强制类型转换 | myFloatValue |
double |
类型为 HEX 的项 | 不进行强制类型转换 | myHexValue |
byte array |
类型为 SMALLFLOAT 的项 | 不进行强制类型转换 | mySmallFloat |
float |
类型为 DATE 的项 | 不进行强制类型转换 | myDate |
java.sql.Date |
类型为 TIME 的项 | 不进行强制类型转换 | myTime |
java.sql.Time |
类型为 TIMESTAMP 的项 | 不进行强制类型转换 | myTimeStamp |
java.sql.Timestamp |
类型为 INTERVAL 的项 | 不进行强制类型转换 | myInterval |
java.lang.String |
浮点文字 | 不进行强制类型转换 | -6.5231E96 | double |
不包含小数的数字项(或非浮点文字);前导零计入文字的位数。 | 不进行强制类型转换,1-4 位 | 0100 |
short |
不进行强制类型转换,5-9 位 | 00100 |
int | |
不进行强制类型转换,9-18 位 | 1234567890 |
long | |
不进行强制类型转换,高于 18 位 | 1234567890123456789 |
java.math.BigInteger | |
包含小数的数字项(或非浮点文字);前导零和结尾零计入文字的位数。 | 不进行强制类型转换,1-6 位 | 3.14159 |
float |
不进行强制类型转换,7-18 位 | 3.14159265 |
double | |
不进行强制类型转换,高于 18 位 | 56789543.222 |
java.math.BigDecimal | |
数字项或非浮点文字,带有或不带小数 | 使用 bigdecimal、biginteger、byte、double、float、short、int 或 long 进行强制类型转换 | X = 42; (byte)X (long)X |
指定的基本类型;但如果值超出该类型的范围,则会丢失精度,符号也可能会更改 |
使用布尔值进行强制类型转换,这表示非零为 true,零为 false | X = 1; (boolean)X |
boolean |
有关 EGL 中的项的内部格式的详细信息,请参阅有关基本类型的帮助页面。
本节给出有关如何使用 Java 访问函数的示例。
// call the constructor of the Java Date class and // assign the new object to the identifier "date". JavaLib.storeNew( (objId)"date", "java.util.Date" ); // call the toString method of the new Date object // and assign the output (today's date) to the chaItem. // In the absence of the cast (objId), "date" // refers to a class rather than an object. charItem = JavaLib.invoke( (objId)"date", "toString" ); // assign the standard output stream of the // Java System class to the identifier "systemOut". JavaLib.storeField( (objId)"systemOut", "java.lang.System", "out" ); // call the println method of the output // stream and print today's date. JavaLib.invoke( (objID)"systemOut","println",charItem ); // The use of "java.lang.System.out" as the first // argument in the previous line would not have been // valid, as the argument must either be a // an identifier already in the object space or a class // name. The argument cannot refer to a static field.
// assign the name of an identifier to an item of type CHAR valueID = "osNameProperty" // place the value of property os.name into the // object space, and relate that value (a Java String) // to the identifier osNameProperty JavaLib.store((objId)valueId, "java.lang.System", "getProperty", "os.name"); // test whether the property value is non-existent // and process accordingly myNullFlag = JavaLib.isNull( (objId)valueId ); if( myNullFlag == 1 ) error = 27; end
当在 EGL 中使用 Java 数组时,请使用 Java 类 java.lang.reflect.Array,如后面的示例所示以及如 Java API 文档所述。由于 Java 数组没有构造函数,所以不能使用 JavaLib.storeNew 来创建 Java 数组。
使用 java.lang.reflect.Array 的静态方法 newInstance 以在对象空间中创建数组。在创建数组之后,使用该类中的其它方法来访问元素。
根据您要创建的是对象数组还是基本类型数组,用于标识类对象的代码会有所不同。与数组进行交互的后续代码也会以此为基础而有所变化。
// Get a reference to the class, for use with newInstance JavaLib.store( (objId)"objectClass", "java.lang.Class", "forName", "java.lang.Object" ); // Create the array in the object space JavaLib.store( (objId)"myArray", "java.lang.reflect.Array", "newInstance", (objId)"objectClass", 5 );
如果要创建存放另一种类型的对象的数组,请更改传递给 JavaLib.store 的第一次调用的类名。例如,要创建字符串对象的数组,传递“java.lang.String”而不是“java.lang.Object”。
length = JavaLib.invoke( "java.lang.reflect.Array", "getLength", (objId)"myArray" ); i = 0; while ( i < length ) JavaLib.store( (objId)"element", "java.lang.reflect.Array", "get", (objId)"myArray", i ); // Here, process the element as appropriate JavaLib.invoke( "java.lang.reflect.Array", "set", (objId)"myArray", i, (objId)"element" ); i = i + 1; end
int length = myArray.length; for ( int i = 0; i < length; i++ ) { Object element = myArray[i]; // Here, process the element as appropriate myArray[i] = element; }
要创建用于存储 Java 基本类型而不是对象的数组,请在使用 java.lang.reflect.Array 之前的步骤中使用另一种机制。特别是,通过访问基本类型类的静态字段 TYPE 来获取 newInstance 的 Class 自变量。
// Get a reference to the class, for use with newInstance JavaLib.storeField( (objId)"intClass", "java.lang.Integer", "TYPE"); // Create the array in the object space JavaLib.store( (objId)"myArray2", "java.lang.reflect.Array", "newInstance", (objId)"intClass", 30 );
如果要创建存放另一种类型的原语的数组,请更改传递给 JavaLib.storeField 的调用的类名。例如,要创建字符数组,请传递“java.lang.Character”而不是“java.lang.Integer”。
length = JavaLib.invoke( "java.lang.reflect.Array", "getLength", (objId)"myArray2" ); i = 0; while ( i < length ) element = JavaLib.invoke( "java.lang.reflect.Array", "getDouble", (objId)"myArray2", i ); // Here, process an element as appropriate JavaLib.invoke( "java.lang.reflect.Array", "setDouble", (objId)"myArray2", i, element ); i = i + 1; end
int length = myArray2.length; for ( int i = 0; i < length; i++ ) { double element = myArray2[i]; // Here, process an element as appropriate myArray2[i] = element; }
Iterator contents = list.iterator(); while( contents.hasNext() ) { Object myObject = contents.next(); // Process myObject }
JavaLib.store( (objId)"contents", (objId)"list", "iterator" ); hasNext = JavaLib.invoke( (objId)"contents", "hasNext" ); while ( hasNext == 1 ) JavaLib.store( (objId)"myObject", (objId)"contents", "next"); // Process myObject hasNext = JavaLib.invoke( (objId)"contents", "hasNext" ); end
// Create a collection from array myArray // and relate that collection to the identifier "list JavaLib.store( (objId)"list", "java.util.Arrays", "asList", (objId)"myArray" );
接着,对列表进行迭代,如前一节所示。
数组到集合的转换仅对对象数组起作用,而对 Java 基本类型数组不起作用。请注意不要将 java.util.Arrays 与 java.lang.reflect.Array 混淆。
如特定于函数的帮助页面所述,许多 Java 访问函数与错误代码相关联。如果发生所列示的某个错误时系统变量 VGVar.handleSysLibraryErrors 的值是 1,EGL 就将系统变量 sysVar.errorCode 设置为非零值。如果发生某个错误时 VGVar.handleSysLibraryErrors 的值为 0,则程序结束。
特别要注意的是 sysVar.errorCode 值“00001000”,这个值指示被调用方法抛出了异常,或者作为类初始化的结果而抛出了异常。
当抛出异常时,EGL 将其存储在对象空间中。如果发生另一个异常,则第二个异常将取代第一个异常。可使用标识 caughtException 来访问所发生的最后一个异常。
在并不常见的情况下,被调用方法抛出的不是异常而是错误,如 OutOfMemoryError 或 StackOverflowError。在这样的情况下,无论系统变量 VGVar.handleSysLibraryErrors 具有何值,程序都结束。
int errorType = 0; Exception ex = null; try { java.io.FileOutputStream fOut = new java.io.FileOutputStream( "out.txt" ); } catch ( java.io.IOException iox ) { errorType = 1; ex = iox; } catch ( java.lang.SecurityException sx ) { errorType = 2; ex = sx; }
VGVar.handleSysLibraryErrors = 1; errorType = 0; JavaLib.storeNew( (objId)"fOut", "java.io.FileOutputStream", "out.txt" ); if ( sysVar.errorCode == "00001000" ) exType = JavaLib.qualifiedTypeName( (objId)"caughtException" ); if ( exType == "java.io.IOException" ) errorType = 1; JavaLib.storeCopy( (objId)"caughtException", (objId)"ex" ); else if ( exType == "java.lang.SecurityException" ) errorType = 2; JavaLib.storeCopy( (objId)"caughtException", (objId)"ex" ); end end end