Java アクセス関数

Java™ アクセス関数 は、EGL システム関数です。これによって、 ユーザーが作成した Java コードで、ネイティブ Java オブジェクトおよびクラス (特にネイティブ・コードの public メソッド、コンストラクター、およびフィールド) にアクセスできます。

EGL フィーチャーは、実行時に EGL Java オブジェクト・スペース が存在する場合に使用可能になります。EGL Java ネームスペースは、一連の名前とそれらの名前 が参照するオブジェクトです。 生成したプログラムとそれらのプ ログラムがローカルで呼び出すすべての生成済み Java コードで、単一のオブジェクト・スペースを使用できます。呼 び出しが直接呼び出しであるか別のローカル生成された Java プログラムを介して いるかにかかわらず、任意のレベルの呼び出しで使用できます。オブジェクト・スペースは任意のネイティブ Java コ ードで使用できるわけではありません。

オブジェクトをネームスペースに格納したりオブジェクト・スペースで検索したりする には、Java アクセス関数を呼び出します。呼び出しでは ID も使用します。各 ID は、オ ブジェクトをオブジェクト・スペースに格納したり、すでに存在する名前と一致させるために使用 されるストリングです。ID が名前と一致すると、コードからその名前に関連付けられ たオブジェクトにアクセスできます。

注: Java アクセス関数を組み込んだ EGL コードを COBOL プログラムとして生成することはできません。
以下に次の各セクションがあります。

EGL および Java の型のマッピング

メソッドに渡すそれぞれの引き数 (およびフィールドに割り当てるそれぞれの値) は、Java オブジェクトまたはプリミティブ型へマップされます。 例えば、EGL プリミティブ型 CHAR の項目は、Java String クラスのオブジェクトとして渡されます。 EGL の型から Java の型へのマッピングが不十分な場合のために、キャスト演算子が提供されています。

Java 名を指定すると、EGL は、値の先頭と最後から、単一バイトのブランクと 2 バイトのブランクを削除します。この値では、大/小文字が区別されます。 切り捨ては、どのキャストよりも先に行われます。この規則は、ストリング・リテラル、および CHAR 型、DBCHAR 型、MBCHAR 型、または UNICODE 型の項目に適用されます。値を objID または null にキャストしない限り、メソッド引き数またはフィールド値の指定時に、このような切り捨ては行われません (例えば、ストリング "my data" は、そのままの形でメソッドに渡されます)。

次の表は、有効なマッピングをすべてまとめたものです。

引き数のカテゴリー Java の型
ストリング・リテラル、または CHAR 型、DBCHAR 型、MBCHAR 型、UNICODE 型の項目 キャストなし
"myString"
java.lang.String
ID を示す objId でキャスト
(objId)"myId"

x = "myId";
(objId)X
ID が参照するオブジェクトのクラス
null でキャスト。これは、完全修飾クラスに null 参照を提供するのに適しています
(null)"java.
lang.Thread"

x = "java.util.
HashMap";
(null)x
指定したクラス
注: (null)"int[]" などの null でキャストされた配列に渡すことはできません
char でキャスト。これは、値の先頭の文字が渡されることを意味します (次の列の例ではそれぞれ "a" が渡されます)
(char)"abc"

X = "abc";
(char)X
char
FLOAT 型の項目または浮動小数点数リテラル キャストなし
myFloatValue
double
HEX 型の項目 キャストなし
myHexValue
バイト配列
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
指定した基本型。ただし、値がその型の範囲を超えると、精度が失われ、符号が変わることがあります。
ブール値へのキャスト。これは、ゼロ以外が真、ゼロが偽であることを意味します。
X = 1;
(boolean)X
boolean

注: 精度が失われるのを回避するために、Java の double には EGL の float 項目を使用し、 Java の float には EGL の smallfloat 項目を使用してください。それ以外の EGL の型を使用すると、多くの場合、結果としての値が丸められます。

EGL 内の項目の内部形式については、『基本型』のページを参照してください。

このセクションでは、Java アクセス関数の使用方法について例を示します。

日付ストリングの出力

次の例では、日付ストリングが出力されます。
  // Java Date クラスのコンストラクターを呼び出し
  // 新規オブジェクトを ID "date" に割り当てます。
JavaLib.storeNew( (objId)"date", "java.util.Date" );

  // 新規 Date オブジェクトの toString メソッドを呼び出し
  // 出力 (本日の日付) を chaItem に割り当てます。
  // キャスト (objId) が存在しない場合、"date" は
  // オブジェクトではなくクラスを参照します。
charItem = JavaLib.invoke( (objId)"date", "toString" );

  // Java System クラスの標準出力ストリームを
  // ID "systemOut" に割り当てます。
  JavaLib.storeField( (objId)"systemOut", 
    "java.lang.System", "out" );

  // 出力ストリームの println メソッドを呼び出し
  // 今日の日付を出力します。
  JavaLib.invoke( (objID)"systemOut","println",charItem );

  // "java.lang.System.out" を
  // 前の行の第 1 引き数として使用すると、
  // 無効です。この引き数は、すでにオブジェクト・スペース内にある
  // 識別子であるか、クラス名であることが必要だからです。
  // この引き数は static フィールドを参照できません。

システム・プロパティーのテスト

次の例では、システム・プロパティーが検索され、値の有無がテストされます。
  // ID の名前を CHAR 型の項目に割り当てます
  valueID = "osNameProperty"

  // プロパティー os.name の値を
  // オブジェクト・スペースに格納し、この値 (Java の String) を ID osNameProperty に
  // 関連付けます
  JavaLib.store((objId)valueId, "java.lang.System",
    "getProperty", "os.name");

  // プロパティー値が存在しないかどうかをテストし、
  // それに応じて処理を実行します
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 は、次の 2 つの引き数を取ります。
  • 作成される配列の型を決定する Class オブジェクト
  • 配列内のエレメント数を指定する数字

Class オブジェクトを識別するコードは、オブジェクト配列、または基本配列のどちらを作成するのかに応じて変化します。配列と対話する後続のコードも、これと同じ基準で変化します。

オブジェクトの配列の使用

次の例は、ID "myArray" を使用してアクセス可能な、5 つのエレメントを持つオブジェクト配列の作成方法を示しています。
  // newInstance で使用するためにクラスへの参照を取得します
  JavaLib.store( (objId)"objectClass", "java.lang.Class",
    "forName", "java.lang.Object" );

  // オブジェクト・スペース内に配列を作成します
  JavaLib.store( (objId)"myArray", "java.lang.reflect.Array",
    "newInstance", (objId)"objectClass", 5 );

異なる型のオブジェクトを保持する配列を作成したい場合は、JavaLib.store の最初の呼び出しに渡すクラス名を変更してください。 String オブジェクトの配列を作成するには、例えば、"java.lang.Object" の代わりに "java.lang.String" を渡します。

オブジェクト配列のエレメントにアクセスするには、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 );

    // ここで、エレメントを適宜処理します
    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];

    // ここで、エレメントを適宜処理します

    myArray[i] = element;
  }  

Java プリミティブの配列の操作

オブジェクトではなく、Java プリミティブを格納する配列を作成するには、java.lang.reflect.Array を使用するより前のステップで、別のメカニズムを使用します。 特に、基本型クラスの静的フィールド TYPE にアクセスして、newInstance の Class 引き数を取得する必要があります。

次の例では、30 のエレメントを持つ整数配列、myArray2 を作成します。
  // newInstance で使用するためにクラスへの参照を取得します
  JavaLib.storeField( (objId)"intClass", 
    "java.lang.Integer", "TYPE");

  // オブジェクト・スペース内に配列を作成します
  JavaLib.store( (objId)"myArray2", "java.lang.reflect.Array",
    "newInstance", (objId)"intClass", 30 );  

異なる型のプリミティブを保持する配列を作成したい場合は、JavaLib.storeField の呼び出しに渡すクラス名を変更してください。 文字配列を作成するには、例えば、"java.lang.Integer" の代わりに "java.lang.Character" を渡します。

基本配列のエレメントにアクセスするには、基本型に固有の 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 );

    // ここで、エレメントを適宜処理します

    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];

    // ここで、エレメントを適宜処理します

    myArray2[i] = element;
  }  

コレクションの使用

list と呼ばれる変数が参照するコレクションを繰り返すには、Java プログラムで次を実行します。
  Iterator contents = list.iterator();

  while( contents.hasNext() )
  { 
    Object myObject = contents.next();
    // myObject を処理します
  }
hasNext は数値データであり、プログラムでは list と呼ばれる ID とコレクションが関連付けられているものと想定します。この場合、次の 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");

    // myObject を処理します
    hasNext = JavaLib.invoke( (objId)"contents", "hasNext" );
  end

配列をコレクションに変換

オブジェクト配列からコレクションを作成するには、java.util.Arrays の asList メソッドを使用します。例を次に示します。
  // 配列 myArray からコレクションを作成し、
  // そのコレクションと ID "list を関連付けます
JavaLib.store( (objId)"list", "java.util.Arrays",
    "asList", (objId)"myArray" );

次に、前のセクションで示したように、list を繰り返します。

配列をコレクションに変換できるのは、オブジェクトの配列の場合に限られます。Java プリミティブの配列をコレクションに変換することはできません。 java.util.Arrays と java.lang.reflect.Array を混同しないように気を付けてください。

エラー処理

多くの場合、Java アクセス関数は、エラー・コードに関連付けられています (関数固有のヘルプのページを参照してください)。 リストされているエラーのいずれかが発生したときに、システム変数 VGVar.handleSysLibraryErrors の値が 1 であると、EGL は、システム変数 sysVar.errorCode にゼロ以外の値を設定します。 エラーのいずれかが発生したときに VGVar.handleSysLibraryErrors の値が 0 の場合は、プログラムが終了します。

sysVar.errorCode の値 "00001000" は、特に重要です。この値は、呼び出されたメソッドにより、またはクラス初期化の結果として、例外がスローされたことを示します。

例外がスローされると、EGL は、それをオブジェクト・スペースに格納します。別の例外が発生すると、2 番目の例外が 1 番目の例外に取って代わります。発生した最後の例外にアクセスするには、ID 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.(C) Copyright IBM Japan 2005.