Funciones de acceso Java

Las funciones de acceso Java son funciones de sistema EGL que permiten al código Java generado acceder a objetos y clases Java nativos; concretamente, para acceder a los métodos, constructores y campos de tipo público del código nativo.

Esta característica de EGL se hace posible durante la ejecución gracias a la presencia del espacio de objetos Java EGL, que es un conjunto de nombres y los objetos a los que estos nombres hacen referencia. Un único espacio de objetos está disponible en el programa generado y en todo el código Java generado al que el programa llama localmente, tanto si las llamadas son directas o a través de otro programa Java generado local, en cualquier nivel de la llamada. El espacio de objetos no está disponible en ningún código Java nativo.

Para almacenar y recuperar objetos del espacio de objetos, invoque las funciones de acceso Java. Las invocaciones incluyen el uso de identificadores, cada uno de los cuales es una serie que se utiliza para almacenar un objeto o para que coincida con un nombre que ya existe en el espacio de objetos. Cuando un identificador coincide con un nombre, el código puede acceder al objeto asociado al nombre.

Las secciones siguientes son estas:

Correlaciones de tipos EGL y Java

Cada uno de los argumentos pasados a un método (y cada valor asignado a un campo) se correlaciona con un objeto o tipo primitivo Java. Los elementos del tipo primitivo EGL CHAR, por ejemplo, se pasan como objetos de la clase Java String. Se suministra un operador de conversión temporal para las situaciones en las que la correlación de tipos EGL con tipos Java no es suficiente.

Si se especifica un nombre Java, EGL elimina blancos de un solo byte y de doble byte del principio y el final del valor, que es sensible a mayúsculas y minúsculas. El truncamiento precede a cualquier conversión temporal. Este norma se aplica a los literales de serie y a los elementos de tipo CHAR, DBCHAR, MBCHAR o UNICODE. Este tipo de truncamiento no se produce si se especifica un argumento de método o valor de campo (por ejemplo, la serie " mis datos " se pasa a un método sin cambios), a menos que convierta temporalmente el valor a objID o nulo.

La tabla siguiente describe todas las correlaciones válidas.

Categoría de argumento Ejemplos Tipo Java
Un literal de serie o un elemento de tipo CHAR, DBCHAR, MBCHAR o UNICODE Sin conversión temporal
"myString"
java.lang.String
Conversión temporal con objId, que indica un identificador
(objId)"myId"

x = "myId";
(objId)X
La clase del objeto al que el identificador hace referencia
Conversión temporal con null, que puede ser adecuado para proporcionar una referencia nula a una clase totalmente calificada
(null)"java.
lang.Thread"

x = "java.util.
HashMap";
(null)x
La clase especificada
Nota: No puede pasarse una matriz convertida temporalmente con null, como por ejemplo (null)"int[]"
Conversión temporal con char, que significa que se pasa el primer carácter del valor (cada ejemplo de la columna siguiente pasa una "a")
(char)"abc"

X = "abc";
(char)X
char
Un elemento de tipo FLOAT o un literal de coma flotante Sin conversión temporal
myFloatValue
double
Un elemento de tipo HEX Sin conversión temporal
myHexValue
matriz de bytes
Un elemento de tipo SMALLFLOAT Sin conversión temporal
mySmallFloat
float
Un elemento de tipo DATE Sin conversión temporal
myDate
java.sql.Date
Un elemento de tipo TIME Sin conversión temporal
myTime
java.sql.Time
Un elemento de tipo TIMESTAMP Sin conversión temporal
myTimeStamp
java.sql.Timestamp
Un elemento de tipo INTERVAL Sin conversión temporal
myInterval
java.lang.String
Literal de coma flotante Sin conversión temporal -6.5231E96 double
Elemento numérico (o literal de coma no flotante) que no contiene decimales; los ceros iniciales se incluyen en el número de dígitos para un literal Sin conversión temporal, 1-4 dígitos
0100
short
Sin conversión temporal, 5–9 dígitos
00100
int
Sin conversión temporal, 9-18 dígitos
1234567890
long
Sin conversión temporal, > 18 dígitos
1234567890123456789
java.math.BigInteger
Elemento numérico (o literales de coma no flotante) que contiene decimales; los ceros iniciales y finales se incluyen en el número de dígitos para un literal Sin conversión temporal, 1–6 dígitos
3.14159
float
Sin conversión temporal, 7-18 dígitos
3.14159265
double
Sin conversión temporal, > 18 dígitos
56789543.222
java.math.BigDecimal
Elemento o literal de coma no flotante, con o sin decimales Conversión temporal con bigdecimal, biginteger, byte, double, float, short, int, long
X = 42;

(byte)X

(long)X
El tipo primitivo especificado; pero, si el valor está fuera de rango para ese tipo, se produce pérdida de precisión y el signo puede cambiar
Conversión temporal con boolean, que significa que no cero es true, cero es false
X = 1;
(boolean)X
boolean

Nota: Para evitar perder precisión, utilice un elemento float EGL para un double Java y un elemento smallfloat EGL para un float Java. Si utiliza otro de los tipos EGL, probablemente se redondeará un valor.

Para obtener detalles acerca del formato interno de los elementos en EGL, consulte las páginas de la ayuda referentes a Tipos primitivos.

Ejemplos

Esta sección ofrece ejemplos de utilización de funciones de acceso Java.

Imprimir una serie de fecha

El ejemplo siguiente imprime una serie de fecha:
  // llamar al constructor de la clase Java Date y
  // asignar el objeto nuevo al identificador "date".
  JavaLib.storeNew( (objId)"date", "java.util.Date" );

  // llamar al método toString del objeto nuevo Date
  // y asignar la salida (fecha de hoy) a chaItem.
  // En ausencia de la conversión temporal (objId), "date" 
  // hace referencia a una clase en lugar de a un objeto.
  charItem = JavaLib.invoke( (objId)"date", "toString" );

  // asignar la corriente de salida estándar de la 
  // clase Java System al identificador "systemOut".
  JavaLib.storeField( (objId)"systemOut", 
    "java.lang.System", "out" );

  // llamar al método println de la corriente de 
  // salida e imprimir la fecha de hoy.
  JavaLib.invoke( (objID)"systemOut","println",charItem );

  // La utilización de "java.lang.System.out" como primer 
  // argumento en la línea anterior no habría sido
  // válida, ya que el argumento debe ser un 
  // identificador que ya se encuentre en el espacio de objetos
  // o un nombre de clase. El argumento no puede hacer referencia a un campo estático.

Probar una propiedad del sistema

El ejemplo siguiente recupera una propiedad del sistema y comprueba la ausencia de un valor:
  // asignar el nombre de un identificador a un elemento de tipo CHAR
  valueID = "osNameProperty"

  // colocar el valor de la propiedad os.name en el 
  // espacio de objetos, y relacionar ese valor (una serie Java) 
  // con el identificador osNameProperty
  JavaLib.store((objId)valueId, "java.lang.System",
    "getProperty", "os.name");

  // comprobar si el valor de propiedad no existe
  // y procesar de acuerdo con ello
  myNullFlag = JavaLib.isNull( (objId)valueId );
  
  if( myNullFlag == 1 )
    error = 27;
  end 

Trabajar con matrices

Al trabajar con matrices Java en EGL, utilice la clase Java java.lang.reflect.Array, como se muestra en los ejemplos posteriores y se describe en la documentación de API Java. No puede utilizar JavaLib.storeNew para crear una matriz Java, ya que las matrices Java no tienen constructores.

Debe utilizar el método estático newInstance de java.lang.reflect.Array para crear la matriz en el espacio de objetos. Una vez creada la matriz, utilice otros métodos de esa clase para acceder a los elementos.

El método newInstance espera dos argumentos:
  • Un objeto Class que determina el tipo de matriz que se crea
  • Un número que especifica cuántos elementos hay en la matriz

El código que identifica el objeto Class varía dependiendo de si se está creando una matriz de objetos o una matriz de primitivos. El código subsiguiente que interactúa con la matriz también varía sobre la misma base.

Trabajar con una matriz de objetos

El ejemplo siguiente muestra cómo crear una matriz de objetos de 5 elementos a la que puede accederse mediante el identificador "myArray":
  // Obtener una referencia a la clase, para utilizarla con newInstance
  JavaLib.store( (objId)"objectClass", "java.lang.Class",
    "forName", "java.lang.Object" );

  // Crear la matriz en el espacio de objetos
  JavaLib.store( (objId)"myArray", "java.lang.reflect.Array",
    "newInstance", (objId)"objectClass", 5 );

Si desea crear una matriz que contenga un tipo de objeto diferente, cambie el nombre de clase que se pasa a la primera invocación de JavaLib.store. Para crear una matriz de objetos String, por ejemplo, pase "java.lang.String" en lugar de "java.lang.Object".

Para acceder a un elemento de una matriz de objetos, utilice los métodos get y set de java.lang.reflect.Array. En el ejemplo siguiente, i y length son elementos numéricos:
  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 );

    // Aquí, procesar el elemento según convenga
    JavaLib.invoke( "java.lang.reflect.Array", "set", 
      (objId)"myArray", i, (objId)"element" ); 
    i = i + 1; 
  end  
El ejemplo anterior es equivalente al siguiente código Java:
  int length = myArray.length; 
  
  for ( int i = 0; i < length; i++ ) 
  { 
    Object element = myArray[i]; 

    // Aquí, procesar el elemento según convenga

    myArray[i] = element; 
  }  

Trabajar con una matriz de primitivos Java

Para crear una matriz que almacene un primitivo Java en lugar de un objeto, utilice un mecanismo diferente en los pasos que preceden a la utilización de java.lang.reflect.Array. En particular, obtenga el argumento Class para newInstance accediendo al campo estático TYPE de una clase de tipo primitivo.

Ej ejemplo siguiente crea myArray2, que es una matriz de enteros de 30 elementos:
  // Obtener una referencia a la clase, para utilizarla con newInstance
  JavaLib.storeField( (objId)"intClass", 
    "java.lang.Integer", "TYPE");

  // Crear la matriz en el espacio de objetos
  JavaLib.store( (objId)"myArray2", "java.lang.reflect.Array",
    "newInstance", (objId)"intClass", 30 );  

Si desea crear una matriz que contenga un tipo de primitivo diferente, cambie el nombre de clase que se pasa a la primera invocación de JavaLib.storeField. Para crear una matriz de caracteres, por ejemplo, pase "java.lang.Character" en lugar de "java.lang.Integer".

Para acceder a un elemento de una matriz de primitivos, utilice los métodos de java.lang.reflect.Array específicos de un tipo primitivo. Tales métodos incluyen getInt, setInt, getFloat, setFloat, etc. En el ejemplo siguiente, length, element e i son elementos numéricos:
  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 ); 

    // Aquí, procesar un elemento según convenga

    JavaLib.invoke( "java.lang.reflect.Array", "setDouble",
      (objId)"myArray2", i, element );
    i = i + 1; 
  end
El ejemplo anterior es equivalente al siguiente código Java:
  int length = myArray2.length;

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

    // Aquí, procesar un elemento según convenga

    myArray2[i] = element;
  }  

Trabajar con colecciones

Para iterar una colección a la que hace referencia una variable denominada list, un programa Java hace lo siguiente:
  Iterator contents = list.iterator(); 

  while( contents.hasNext() ) 
  { 
    Object myObject = contents.next();
    // Procesar myObject
  }
Supongamos que hasNext contiene datos numéricos y que el programa ha relacionado una colección con un identificador denominado list. El siguiente código EGL es equivalente al código Java descrito anteriormente:
  JavaLib.store( (objId)"contents", (objId)"list", "iterator" );
  hasNext = JavaLib.invoke( (objId)"contents", "hasNext" ); 

  while ( hasNext == 1 ) 
    JavaLib.store( (objId)"myObject", (objId)"contents", "next");

    // Procesar myObject
    hasNext = JavaLib.invoke( (objId)"contents", "hasNext" );
  end

Convertir una matriz en una colección

Para crear una colección a partir de una matriz de objetos, utilice el método asList de java.util.Arrays, como se muestra en el ejemplo siguiente:
  // Crear una colección a partir de la matriz myArray 
  // y relacionar esa colección con el identificador "list 
  JavaLib.store( (objId)"list", "java.util.Arrays",
    "asList", (objId)"myArray" );

A continuación, iterar sobre list, como se muestra en la sección anterior.

La transferencia de una matriz a una colección sólo funciona con una matriz de objetos, no con una matriz de primitivos Java. tenga cuidado de no confundir java.util.Arrays con java.lang.reflect.Array.

Manejo de errores

Muchas de las funciones de acceso Java están asociadas con códigos de error, como se describe en las páginas de la ayuda específicas de las funciones. Si el valor de la variable de sistema VGVar.handleSysLibraryErrors es 1 cuando se produce uno de los errores indicados, EGL establece la variable de sistema sysVar.errorCode en un valor no cero. Si el valor de VGVar.handleSysLibraryErrors es 0 cuando se produce uno de los errores, el programa finaliza.

Es de particular interés el valor de sysVar.errorCode "00001000", que indica que un método invocado ha lanzado una excepción o como resultado de una inicialización de clase.

Cuando se lanza una excepción, EGL la almacena en el espacio de objetos. Si se produce otra excepción, la segunda ocupa el lugar de la primera. Puede utilizar el identificador caughtException para acceder a la última excepción producida.

En una situación inusual, un método invocado lanza no una excepción, sino un error como, por ejemplo, OutOfMemoryError o StackOverflowError. En tal caso, el programa finaliza independientemente del valor de la variable de sistema VGVar.handleSysLibraryErrors.

El siguiente código Java muestra cómo un programa Java puede tener varios bloques catch para manejar diferentes tipos de excepciones. Este código intenta crear un objeto FileOutputStream. Una anomalía provoca que el código establezca una variable errorType y que almacene la excepción que se ha lanzado.
  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;
  } 
El siguiente código EGL es equivalente al código Java anterior:
 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
Condiciones de uso | Comentarios
(C) Copyright IBM Corporation 2000, 2005. Reservados todos los derechos.