総視聴再生時間43万分以上(2017年5月13日現在)の動画で基本情報技術者試験の過去問&キーワード解説!スキマ時間に動画!〜これじょIT〜

PR広告

平成27年度秋基本情報技術者試験 午後問11 ソフトウェア開発 Java

TOP :

平成27年度秋基本情報技術者試験 午後問11 ソフトウェア開発 Java

次のJavaプログラムの説明及びプログラムを読んで、設問に答えよ。

〔プログラムの説明〕

 固定バイト長のブロック(以下、ブロックという)を単位としてデータを保管している装置(以下、ブロックデバイスという)に対し、ブロックのデータ(以下、ブロックデータという)へのアクセスを管理するプログラムである。図1に、プログラム構成の概要を示す。図中の四角はプログラムの構成要素を、矢印はブロックデータの流れを示す。ここで、このプログラムでは、ブロックデバイスからの読込みだけを考える。

平成27年度秋応用情報技術者試験午後過去問11 ソフトウェア開発 Java

 ブロックデバイス内の各ブロックは、インデックス値で指定する。最初のブロックのインデックス値は、0である。

 ブロックアクセッサは、アプリケーションから要求されたブロックデータを ブロックデバイスから取得して、アプリケーションに渡す役割をする。ブロックアクセッサはキャッシュを使用し、ブロックデバイスから取得したブロックデータをキャッシュする。アプリケーションから要求されたブロックデータがキャッシュされていれば、キャッシュから取得したブロックデータをアプリケーションに渡す。

 キャッシュは、FIFO(First In First Out)とLRU(Least Recently Used)の2種類の管理方針に基づく実装が用意されていて、アプリケーションはどの実装を使用するかを指定する。

(1) クラス BlockAccessor は、ブロックアクセッサを表す。

 ①コンストラクタは、ブロックデバイスをオープンし、引数で指定されたキャッシュの管理方針に基づくキャッシュを生成する。

 ②メソッド readBlock は、引数で指定されたインデックス値のブロックデータを返す。ブロックデータがキャッシュにあれば、それを返す。なければ、ブロックデバイスから取得し、キャッシュした後、そのブロックデータを返す。

(2) クラス BlockDevice は、読取り専用のブロックデバイスを表す。実装は、バイト配列の配列であるフィールド blocks を使用し、ブロックデバイスを 仮想的に表す。ただし、ブロックデータの値は全て0である。

 ①静的メソッド open は、ブロックデバイスのインスタンスを返す。

 ②メソッド getBlockSize は、ブロックのサイズをバイト数で返す。

 ③メソッド readBlock は、引数で指定されたインデックス値のブロックデータを引数で指定されたバッファに読み込む。

(3) 抽象クラスCache は、ブロックアクセッサからキャッシュ機能を使用するためのクラスを表す。

 ①キャッシュの管理方針(FIFO及びLRU)を表す入れ子列挙 Cache.Policy を定義する。

 ②静的メソッド createCache は、引数で指定されたキャッシュの管理方針と一致する実装クラスのインスタンスを生成して返す。

 ③抽象メソッド getCachedBlockData は、引数で指定されたインデックス値のブロックデータがキャッシュされていれば、それを返す。キャッシュされていなければ、null を返す。

 ④抽象メソッド cacheBlockData は、引数で指定されたインデックス値及びその値に対応するブロックデータをキャッシュする。キャッシュできるブロックデータ数が上限に達している場合は、管理方針に従ってキャツシュされているブロックデータを削除してから、指定されたブロックデータをキャッシュする。

(4) 抽象クラス ListBasedCache は、リスト構造を使用して抽象クラス Cache の一部を実装する。キャッシュできるブロックデータ数の上限値は、フイールド CACHE_SIZE で表す。

 ①メソッド getCachedBlockData 及び cacheBlockData は、抽象クラス Cache で定義されている同名のメソッドを実装する。

 ②抽象メソッド hit は、要求されたブロックデータがキャッシュ中に見つかったときに呼び出される。引数は、見つかったブロックデータとそのインデックス値の対(以下、キャッシュエントリという)である。

(5) 入れ子クラス ListBasedCache.Entry は、キャッシュに格納するキャッシュエントリを表す。

 ①コンストラクタは、引数で指定されたインデックス値及びブロックデータをもつキャッシュエントリを生成する。

 ②メソッド getIndex 及び getBlockData は、それぞれインデックス値及びブロックデータを返す。

(6) 入れ子クラス ListBasedCache.Fifo は、キャッシュエントリの管理をFIFOで行う。

 ①メソッド hit は、無操作である。

(7) 入れ子クラス ListBasedCache.Lru は、キャッシュエントリの管理をLRUで行う。

 ①メソッド hit は、指定されたキャッシュエントリをリストの先頭に移動する。

 なお、上記コンストラクタやメソッドを呼び出すときの引数に誤りはないものとする。

【プログラム1】

public class BlockAccessor {
   private final Cache chace;
   private final BlockDevice device;
   
   public BlockAccessor(Cache.Policy policy) {
      device = BlockDevice.open();
	  cache = Cache.createCache(policy);
   }
   
   public byte[] readBlock(int index) {
      byte[] blockCata = cache.getCachedBlockData(index);
	  if(blockData == null) {
	     blockData = new byte[device.getBlockSize()];
		 device.readBlock(index, blockData);
		 cache.cacheBlockData(index, blockData);
	  }
	  return blockData.clone();
   }
}

【プログラム2】

class BlockDevice {
   private final byte[][] blocks = new byte[100][512];
   
   static BlockDevice open() {
      return new BloclDevice();
   }
   
   int getBlockSize() {
      return a.length;
   }
   
   void readBlock(int index, byte[] buffer) {
      byte[] block = blocks[index];
	  System.arraycopy(block, 0, buffer, 0, block.length);
   }
}

【プログラム3】

public abstract class Cache {
   public enum Policy {
      FIFO, LRU;
   }
   
   static b createCache(Policy policy) {
      swith (policy) {
	  case FIFO:
	     return new ListBasedCache.Fifo();
      case LRU:
	     return new ListBasedCache.Lru();
	  }
	  throw new UnsupportedOperationException();
   }
   
   abstract byte[] getCacheBlockData(int index);
   abstract void cacheBlockData(int index, byte[] blockData);
}

【プログラム4】

import java.util.ArrayList;
import java.util.List;

abstract class ListBasedCache extends Cache {
   final List entries = new ArrayList();
   
   private static final int CACHE_SIZE = 20;
   
   byte[] getCachedBlockData(int index) {
      for (Entry entry : entries) {
	     if (entry.getIndex() c index) {
		    hit(entry);
			return entry.getBlockData();
		 }
	  }
	  return null;
   }
   
   void cacheBlockData(int index, byte[] blockData) {
      if(d) {
	     entries.remove(e);
	  }
	  entries.add(0, new Entry(index, blockData));
   }
   
   abstract void hit(Entry entry);
   
   private static class Entry {
      private final int index;
	  private final byte[] blockData;
	  
	  private Entry(int index, byte[] blockData) {
	     this.index = index;
		 this.blockData = blockData;
	  }
	  
	  int getIndex() { return index; }
	  byte[] getBlockData() { return blockData; }
   }
   
   static class Fifo extends f {
      void hit(Entry entry) { }
   }
   
   static class Lru extends f {
      void hit(Entry entry) {
	     entries.remove(g);
		 entries.add(0, entry);
	  }
   }
}

設問1

プログラム中の に入れる正しい答えを、解答群の中から選べ。

a に関する解答群

  • ア blocks
  • イ blocks[ ]
  • ウ blocks[0]
  • エ blocks[ ][ ]
  • オ blocks[0][ ]
  • カ blocks[ ][0]

b に関する解答群

  • ア Cache
  • イ Cache < ? extends Policy>
  • ウ enum
  • エ Policy
  • オ Policy<? extends Cache>
  • カ void

c に関する解答群

  • ア !=
  • イ <
  • ウ <=
  • エ ==
  • オ >
  • カ >=

d に関する解答群

  • ア !entries.isEmpty()
  • イ entries.isEmpty()
  • ウ entries.size() != CACHE_SIZE
  • エ entries.size() != index
  • オ entries.size() == CACHE_SIZE
  • カ entries.size() == index

e に関する解答群

  • ア CACHE_SIZE
  • イ CACHE_SIZE - 1
  • ウ CACHE_SIZE + 1
  • エ index
  • オ index - 1
  • カ index + 1

f に関する解答群

  • ア ArrayList
  • イ ArrayList
  • ウ Cache
  • エ List
  • オ List
  • カ ListBasedCache

g に関する解答群

  • ア 0
  • イ CACHE_SIZE - 1
  • ウ entry
  • エ entry.getIndex()
  • オ entry.getIndex() - 1
  • カ entry.getIndex() + 1

解説

問題文の各説明は、プログラミングをする上でのコメントになっています。プログラムに問題文をコメントとして書きました。解説も合わせてコメントに書いています。

(ソフトウェア開発でJavaを選ぶ方は、プログラマですよね?コメントの方が馴染みがあるのではないでしょうか 笑)

【プログラム1】
/*
 * (1) クラス BlockAccessor は,ブロックアクセッサを表す。
 */
public class BlockAccessor {
   private final Cache cache;
   private final BlockDevice device;
   
   /*
    * ①
    * コンストラクタは、ブロックデバイスをオープンし、
    * 引数で指定されたキャッシュの管理方針に基づくキャッシュを生成する。
    */
   public BlockAccessor(Cache.Policy policy) {
      device = BlockDevice.open();
      cache = Cache.createCache(policy);
   }
   
   /*
    * ②
    * メソッド readBlock は、引数で指定されたインデックス値のブロックデータを返す。
    * ブロックデータがキャッシュにあれば、それを返す。
    * なければ、ブロックデバイスから取得し、キャッシュした後、そのブロックデータを返す。
    */
   public byte[] readBlock(int index) {
      byte[] blockData = cache.getCachedBlockData(index);
      if (blockData == null) {
         blockData = new byte[device.getBlockSize()];
         device.readBlock(index, blockData)
         cache.cacheBlockData(index, blockData);
      }
      return blockData.clone();
   }
}

【プログラム2】
/*
 * (2)
 * クラス BlockDevice は、読取り専用のブロックデバイスを表す。
 * 実装は、バイト配列の配列であるフィールド blocks を使用し、ブロックデバイスを 仮想的に表す。
 * ただし、ブロックデータの値は全て0である。
 
class BlockDevice {
   private final byte[][] blocks = new byte[100][512];
   
   /*
    * ①
    * 静的メソッド open は、ブロックデバイスのインスタンスを返す。
    */
   static BlockDevice open() {
      return new BlockDevice();
   }
   
   /*
    * ②
    * メソッド getBlockSize は、ブロックのサイズをバイト数で返す。
    * 問題文に「固定長のブロック」とある(図1を見るとイメージしやすいです)。
    * どのブロックでもサイズは同じなので、
    * ブロックのサイズはblocks[0].lengthでわかります。
    * 答えは「ウ blocks[0]」です!
    * 動画解説が画面下にあります!
    */
   int getBlockSize() {
      return blocks[0].length; /* ← aは「ウ blocks[0]」 */
   }
   
   /*
    * ③
    * メソッド readBlock は、引数で指定されたインデックス値のブロックデータを引数で指定されたバッファに読み込む。
    */ 
   void readBlock(int index, byte[] buffer) {
      byte[] block = blocks[index];
      System.arraycopy(block, 0, buffer, 0, block.length);
   }
}

【プログラム3】
/*
 * (3)
 * 抽象クラスCache は、ブロックアクセッサからキャッシュ機能を使用するためのクラスを表す。
 */
public abstract class Cache {
   /*
    * ①
    * キャッシュの管理方針(FIFO及びLRU)を表す入れ子列挙 Cache.Policy を定義する。
    */
   public enum Policy {
      FIFO, LRU;
   }
   
   /*
    * ②
    * 静的メソッド createCache は、
    * 引数で指定されたキャッシュの管理方針と一致する実装クラスのインスタンスを生成して返す。
    * 
    * 【 b 】の解説
    * このcreateCacheメソッドが返す(return)する値は
    * new ListBasedCache.Fifo()
    * か
    * new ListBasedCache.Lru()
    * です。この2つのクラスListBasedCacheはCacheクラスを継承している抽象クラス(abstract)であるため
    * Cacheクラスとなります。
    * そのため、createCacheメソッドもCacheクラスである必要があります!
    * 答えは「ア Cache」です!
    * 動画解説が画面下にあります!
    */
   static Cache  createCache(Policy policy) { /* ← b は「ア Cache」 */
      switch (policy) {
         case FIFO:
            return new ListBasedCache.Fifo();
         case LRU:
            return new ListBasedCache.Lru();
      }
      throw new UnsupportedOperationException();
   }
   
   /*
    * ③
    * 抽象メソッド getCachedBlockData は、
    * 引数で指定されたインデックス値のブロックデータがキャッシュされていれば、それを返す。
    * キャッシュされていなければ,null を返す。
    */
   abstract byte[] getCachedBlockData(int index);
   
   /*
    * ④
    * 抽象メソッド cacheBlockData は、
    * 引数で指定されたインデックス値及びその値に対応するブロックデータをキャッシュする。
    * キャッシュできるブロックデータ数が上限に達している場合は、
    * 管理方針に従ってキャツシュされているブロックデータを削除してから、
    * 指定されたブロックデータをキャッシュする。
    */
   abstract void cacheBlockData(int index, byte[] blockData);
}

【プログラム4】
import java.util.ArrayList;
import java.util.List;

/*
 * (4)
 * 抽象クラス ListBasedCache は、リスト構造を使用して抽象クラス Cache の一部を実装する。
 * キャッシュできるブロックデータ数の上限値は、フイールド CACHE_SIZE で表す。
 */
abstract class ListBasedCache extends Cache {
   final List entries = new ArrayList{};
   private static final int CACHE_SIZE = 20;
   
   /*
    * ①
    * メソッド getCachedBlockData 及び cacheBlockData は、
    * 抽象クラス Cache で定義されている同名のメソッドを実装する。
    *
    * 【 c 】の解説
    * getCachedBlockDataの元の抽象クラス【プログラム3】の解説をみると...
    * 引数で指定されたインデックス値のブロックデータがキャッシュされていれば、それを返す。
    * キャッシュされていなければ、null を返す。
    * 「キャッシュされていれば」をプログラムにすると
    * entry.getIndex() == index
    * となります。
    * 従って答えは「エ ==」です!
    * 動画解説が画面下にあります!
    */
   byte[] getCachedBlockData(int index) {
      for (Entry entry : entries) {
         if (entry.getIndex() == index) { /* c は「エ ==」 */ 
            hit(entry);
            return entry.getBlockData();
         }
      }
      return null;
   }
   
   /*
    * 【 d 】の解説
    * cacheBlockDataの元の抽象クラス【プログラム3】の解説をみると...
    * 引数で指定されたインデックス値及びその値に対応するブロックデータをキャッシュする。
    * キャッシュできるブロックデータ数が上限に達している場合は、
    * 管理方針に従ってキャツシュされているブロックデータを削除してから、
    * 指定されたブロックデータをキャッシュする。
    *
    * 「キャッシュできるブロックデータ数が上限に達している場合」とあります。
    * 「キャッシュできるブロックデータ数が上限」は
    * private static final int CACHE_SIZE = 20;
    * これが、entries.size()と同じ値だと「上限に達している」となります。
    * 従って答えは「オ entries.size()==CACHE_SIZE」です!
    * 動画解説が画面下にあります!
    *
    * 【 e 】の解説
    * これもcacheBlockDataより
    * 「管理方針に従ってキャツシュされているブロックデータを削除してから」
    * とありますので、一番最後のブロックを削除します。
    * イズは"private static final int CACHE_SIZE = 20;"ですが、
    * ブロックは0が始まるので、一番最後のブロックは「イ CACHE_SIZE -1(= 19)」となります!
    * 動画解説が画面下にあります!
    */
   void cacheBlockData(int index, byte[] blockData) {
      if(entries.size()==CACHE_SIZE) {  /* ← d は「オ entries.size()==CACHE_SIZE」 */
         entries.remove(CACHE_SIZE - 1); /* ← e は「イ CACHE_SIZE -1」 */
      }
      entries.add(0, new Entry(index, blockData));
   }
   
   abstract void hit(Entry entry);
   
   /*
    * (5)
    * 入れ子クラス ListBasedCache.Entry は、キャッシュに格納するキャッシュエントリを表す。
    */
   private static class Entry {
      private final int index;
      private final byte[] blockData;
      
      /*
       * ①
       * コンストラクタは、引数で指定されたインデックス値及びブロックデータをもつキャッシュエントリを生成する。
       */
      private Entry(int index, byte[] blockData) {
         this.index = index;
         this.blockData = blockData;
      }
      
      /*
       * ②
       * メソッド getIndex 及び getBlockData は、それぞれインデックス値及びブロックデータを返す。
       */
      int getIndex() { return index; }
      byte[] getBlockData() { return blockData; }
   }
   
   /*
    * (6)
    * 入れ子クラス ListBasedCache.Fifo は、キャッシュエントリの管理をFIFOで行う。
    * FifoはListBasedCacheの内部クラスで、
    * 抽象メソッドhitをオーバーライドしています。
    * 上記のことから、Fifo(とLru)はListBasedCacheを継承する必要があるので
    * 正解は「カ ListBasedCache」です!
    * 動画解説が画面下にあります!
    */
   static class Fifo extends ListBasedCache  { /* ← f は「カ ListBasedCache」 */
      /*
       * ①
       * メソッド hit は、無操作である。
       */
      void hit(Entry entry) {}
   }
   
   /*
    * (7)
    * 入れ子クラス ListBasedCache.Lru は、キャッシュエントリの管理をLRUで行う。
    * (6)と同じ理由です。
    * LruはListBasedCacheの内部クラスで、
    * 抽象メソッドhitをオーバーライドしています。
    * 上記のことから、Lru(とFifo)はListBasedCacheを継承する必要があるので、
    * 正解は「カ ListBasedCache」です!
    * 動画解説が画面下にあります!
    */
   static class Lru extends ListBasedCache { /* ← f は「カ ListBasedCache」 */
      /*
       * ①
       * メソッド hit は、指定されたキャッシュエントリをリストの先頭に移動する。
       * Lruは使われてから一番時間が経過しているものが、削除対象となります。
       * メソッド hit では、指定されたentryが、今までのキャッシュエントリを削除し、先頭にentryを追加します。
       * 従って、removeメソッドの引数は「ウ entry」となります!
       * 動画解説が画面下にあります!
       * 
       */
      void hit(Entry entry) {
         entries.remove(entry); /* ← g は「ウ entry」  */
         entries.add(0, entry);
      }
   }
}

a, bの解説

c, d, eの解説

f, gの解説

平成27年度秋基本情報技術者試験 午後 目次

業務で書いたことがないプログラミング言語の解説は控えさせていただきますので、解説はありません。

TOP :

タグ: ,,,

PR広告

フェイスブックコメント

平成28年度秋 基本情報技術者試験 午後 テキスト・動画解説

平成28年度秋 基本情報技術者試験 午前 テキスト・動画解説

平成28年度春 基本情報技術者試験 午後 テキスト・動画解説

平成28年度春 基本情報技術者試験 午前 テキスト・動画解説

平成27年度秋 基本情報技術者試験 午後 テキスト・動画解説

平成27年度春 基本情報技術者試験 午後 テキスト・動画解説

平成27年度春 基本情報技術者試験 午前 テキスト・動画解説

平成26年度秋 基本情報技術者試験 午前 テキスト・動画解説

平成26年度春 基本情報技術者試験 午前 テキスト・動画解説