Java アクセス関数

Java™ アクセス関数は、EGL システム関数です。これは、ユーザーの Java コードを使用したローカル Java オブジェクトおよびクラスへのアクセスに使用されます。 特に、これらの関数は、public メソッド、コンストラクター、およびローカル・コードのフィールドにアクセスします。これらは、EGL が以前のバージョンとの互換性のためにのみ保守している古い関数です。新規コードの場合は、より強力な ExternalType 構文を使用してください。詳しくは、『ExternalType パーツ』を参照してください。

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

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

メソッドに渡すそれぞれの引数 (およびフィールドに代入するそれぞれの値) は、Java オブジェクトまたはプリミティブ型にマップされます。詳しくは、『EGL プリミティブ型の Java へのマッピング』を参照してください。

Java アクセス関数を組み込んだ EGL コードを COBOL プログラムとして生成することはできません。

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

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

次の例では、システム・プロパティーが検索され、値の有無がテストされます。
  // 識別子の名前を CHAR 型の変数に代入します
  valueID = "osNameProperty"

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

  // プロパティー値が存在しないかどうかをテストし、
  // それに応じて処理を実行します
  myNullFlag = javaLib.isNull( valueId as "objID:java" );
  
  if( myNullFlag == 1 )
    error = 27;
  end 

配列の使用

EGL で Java 配列を扱うときは、java.lang.reflect.Array Java クラスを使用します (詳しくは、Java API ドキュメンテーションの説明を参照してください)。Java 配列はコンストラクターを持たないため、 javaLib.storeNew() を使用して Java 配列を作成することはできません。

オブジェクト・スペースに配列を作成するには、java.lang.reflect.Array の静的メソッド newInstance() を使用します。 配列を作成した後で、そのクラスの他のメソッドを使用して、要素にアクセスします。

newInstance() メソッドは、2 つの引数を取ります。
  • 作成される配列の型を決定する Class オブジェクト
  • 配列内の要素数を指定する数字

Class オブジェクトを識別するコードは、オブジェクト配列、または基本配列のどちらを作成するかによって変わります。 次のセクションの例で、このバリエーションを示します。

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

次の例は、識別子 "myArray" を使用して接続な、5 つの要素を持つオブジェクト配列の作成方法を示しています。
  // newInstance() で使用するために、クラスへの参照を取得します
  javaLib.store( "objectClass" as "objID:java", "java.lang.Class",
    "forName", "java.lang.Object" );

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

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

オブジェクト配列の要素にアクセスするには、 java.lang.reflect.Array の get メソッドと set メソッドを使用します。次の例では、 ilength が数値変数となっています。
  length = javaLib.invoke( "java.lang.reflect.Array", 
    "getLength", "myArray" as "objID:java" );
  i = 0; 

  while ( i < length ) 
    javaLib.store( "element" as "objID:java", "java.lang.reflect.Array",
      "get", "myArray" as "objID:java", i );

    // ここで、適宜要素を処理します
    javaLib.invoke( "java.lang.reflect.Array", "set", 
      "myArray" as "objID:java", i, "element" as "objID:java" ); 
    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 引数を取得する必要があります。

次の例は、myArray2 (30 の要素を持つ整数配列) を作成する例です。
  // newInstance で使用するためにクラスへの参照を取得します
  javaLib.storeField( "intClass" as "objID:java", 
    "java.lang.Integer", "TYPE");

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

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

基本配列の要素にアクセスするには、基本型に固有の java.lang.reflect.Array メソッドを使用します。 このようなメソッドには、getInt()setInt()getFloat()setFloat() などがあります。 次の例では、lengthelement、および i が数値変数となっています。
  length = javaLib.invoke( "java.lang.reflect.Array", 
    "getLength", "myArray2" as "objID:java" ); 
  i = 0; 

  while ( i < length )
    element = javaLib.invoke( "java.lang.reflect.Array", 
      "getDouble", "myArray2" as "objID:java", i ); 

    // ここで、適宜要素を処理します

    javaLib.invoke( "java.lang.reflect.Array", "setDouble",
      "myArray2" as "objID:java", 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 という名前の識別子とコレクションが関連付けられているものと想定します。 次の EGL コードは、前述の Java コードと同等です。
  javaLib.store( "contents" as "objID:java", 
                 "list" as "objID:java", "iterator" );
  hasNext = javaLib.invoke( "contents"  as "objID:java", "hasNext" ); 

  while ( hasNext ) 
    javaLib.store( "myObject" as "objID:java", 
                   "contents" as "objID:java", "next");

    // myObject を処理します
    hasNext = javaLib.invoke( "contents" as "objID:java", "hasNext" );
  end

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

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

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

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

エラー処理

デフォルトのエラー処理 (v60ExceptionCompatibility を NO に設定) を使用している場合、 呼び出された Java コードが例外をスローすると、EGL は JavaObjectException をスローすることによって応答します。EGL 側のエラーは、RuntimeException を引き起こします。 個々の関数の『エラーに関する考慮事項』も参照してください。

V6 の例外互換性を使用する場合 (『v60ExceptionCompatibility』を参照)、javaLib 内の関数によって設定される sysVar.errorCode の値を使用できます (これらの関数についての個々のトピックで説明しています)。

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

例外がスローされると、EGL は、それをオブジェクト・スペースに格納します。別の例外が発生すると、2 番目の例外が 1 番目の例外に取って代わります。発生した最新の例外にアクセスするには、識別子 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( "fOut" as "objID:java",
                    "java.io.FileOutputStream", "out.txt" );

  if ( sysVar.errorCode == "00001000" )
    case ( javaLib.qualifiedTypeName( "caughtException" as "objID:java" ) )

      when ( "java.io.IOException" )
        errorType = 1;
        javaLib.storeCopy( "caughtException" as "objID:java", 
                           "ex" as "objID:java" );
      when ( "java.lang.SecurityException" )
        errorType = 2;
        javaLib.storeCopy( "caughtException" as "objID:java",
                           "ex" as "objID:java" );
    end
  end

フィードバック