Java 访问函数

Java™ 访问函数是 EGL 系统函数,它们允许生成的 Java 代码访问本机 Java 对象和类;具体地说,允许 Java 代码访问本机代码的公用方法、构造函数和字段。

在运行时,由于存在 EGL Java 对象空间而使此 EGL 功能成为可能,其中,EGL Java 对象空间是一组名称以及那些名称所引用的对象。有一个对象空间可供生成的程序以及该程序以本地方式调用的所有 Java 生成代码使用,无论那些调用是直接的还是通过另一个本地 Java 生成程序进行的均如此,并且可用于任何级别的调用。此对象空间不能用在任何本机 Java 代码中。

要在对象空间中存储和检索对象,请调用 Java 访问函数。这些调用包括使用标识,每个标识都是用来存储对象或用来匹配对象空间中已存在的名称的字符串。当标识与名称相匹配时,代码就可以访问与该名称相关联的对象。

接下来的几个部分如下所示:

EGL 与 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 双精度,并使用 EGL smallfloat 项来表示 Java 浮点。使用其它 EGL 类型中的某个类型可能导致值被四舍五入。

有关 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 以在对象空间中创建数组。在创建数组之后,使用该类中的其它方法来访问元素。

方法 newInstance 期望两个自变量:
  • 一个类对象,它确定正在创建的数组的类型
  • 一个数字,它指定数组中有多少个元素

根据您要创建的是对象数组还是基本类型数组,用于标识类对象的代码会有所不同。与数组进行交互的后续代码也会以此为基础而有所变化。

使用对象数组

以下示例显示如何创建可使用标识“myArray”来访问的 5 个元素的对象数组:
  // 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”。

要访问对象数组的元素,请使用 java.lang.reflect.Array 的 get 和 set 方法。在以下示例中,i 和 length 是数字项:
  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
    
上一个示例等同于下列 Java 代码:
  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 基本类型而不是对象的数组,请在使用 java.lang.reflect.Array 之前的步骤中使用另一种机制。特别是,通过访问基本类型类的静态字段 TYPE 来获取 newInstance 的 Class 自变量。

以下示例创建 myArray2,这是包含 30 个元素的整数数组:
  // 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”。

要访问基本类型数组的元素,请使用特定于基本类型的 java.lang.reflect.Array 方法。这样的方法包括 getInt、setInt、getFloat 和 setFloat 等等。在以下示例中,length、element 和 i 是数字项:
  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
上一个示例等同于下列 Java 代码:
  int length = myArray2.length;

  for ( int i = 0; i < length; i++ )
  { 
    double element = myArray2[i];

    // Here, process an element as appropriate

    myArray2[i] = element;
  }  

使用集合

要对名为 list 的变量所引用的集合进行迭代,Java 程序执行以下操作:
  Iterator contents = list.iterator();

  while( contents.hasNext() )
  { 
    Object myObject = contents.next();
    // Process myObject
  }
假定 hasNext 是数字数据,并且程序将一个集合与名为 list 的标识相关。以下 EGL 代码等同于前面描述的 Java 代码:
  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

将数组转换为集合

要根据对象数组来创建集合,请使用 java.util.Arrays 的 asList 方法,如以下示例所示:
  // 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 具有何值,程序都结束。

下列 Java 代码显示 Java 程序可以如何使用多个 catch 块来处理不同类型的异常。此代码尝试创建 FileOutputStream 对象。发生故障,导致代码设置 errorType 变量并存储所抛出的异常。
  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;
  } 
以下 EGL 代码等同于前面的 Java 代码:
 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
使用条款 | 反馈
(C) Copyright IBM Corporation 2000, 2005. All Rights Reserved.