令和元年秋期試験午前問題 午後問11

午前試験免除制度対応!基本情報技術者試験のeラーニング【独習ゼミ】

問11 ソフトウェア開発(Java)

次のJavaプログラムの説明及びプログラムを読んで,設問1,2に答えよ。
(Javaプログラムで使用するAPIの説明は,こちらを参照してください。)

〔プログラムの説明〕
 スマートフォンやタブレット端末といった携帯端末に通知メッセージを配信するシステム(以下,通知システムという)を模したプログラムである。この通知システムは,メール着信を通知するメッセージを非同期で携帯端末に配信する。このプログラムでは,通知メッセージを配信する処理及び各携帯端末の処理を,それぞれ独立したスレッドとして実行する。
 このプログラムは,次のインタフェース及びクラスから成る。ここで,各コンストラクタ及びメソッドには,正しい引数が与えられるものとする。
  • インタフェース NotificationListener は,通知メッセージを受け取るためのメソッドを定義する。以下,NotificationListener のインスタンスをリスナという。
    1. メソッド onNotificationReceived は,通知メッセージを受信したときに呼び出される。受信した通知メッセージは,引数の文字列のリストで与えられる。
  • クラス MobileDevice は,携帯端末を表す。
    1. コンストラクタは,引数で指定された携帯端末名及びリスナをもつ携帯端末を生成する。
    2. メソッド getListener はリスナを,getName は携帯端末名を返す。
  • クラス Notifier は,携帯端末の管理や通知メッセージの配信などを行う。Notifier のインスタンスは,シングルトン(Java仮想計算機内で唯一の存在)である。
    1. メソッド register は,引数で指定された利用者名とその携帯端末名を登録する。指定された利用者名に対応する携帯端末名が既に登録されている場合は,その利用者名に対応する携帯端末名として追加登録する。
    2. メソッド send は,引数で指定された利用者名で登録されている各携帯端末に,引数で指定された文字列を通知メッセージとして配信する。携帯端末に対して未配信の通知メッセージがある場合,引数のメッセージを未配信のメッセージリストに追加する。
    3. メソッド loopForMessages は,引数で指定された携帯端末に対して,通知メッセージがあれば携帯端末のリスナに通知し,なければ通知メッセージを受け取れる状態(以下,待ち受け状態という)にする。この処理を,通知システムが停止されるまで繰り返す。
    4. メソッド shutdown は,通知システムを停止する。未配信の全メッセージ,全利用者名及び全携帯端末名の登録情報を削除し,登録されている全携帯端末の待ち受け状態を解除する。
  • クラスTesterは,フログラム1~3をテストする。
    1. メソッド main は,利用者名 Taro の携帯端末名 phone 及び tablet を通知システムに登録して,Taro にメッセージを送信する。その後,通知システムを停止する。
    2. メソッド createUserMobileDevice は,利用者名とその携帯端末名を登録して,通知メッセージを受信できる状態にする処理を,新しく生成したスレッドで実行する。
 図1は,クラス Tester のメソッド main を実行して得られた出力の例である。ここで,プログラムは,スレッドの実行速度及び事象発生に対する応答が十分速いシステムで実行されるものとする。また,スレッドのスケジューリングによって,各行の出力順は異なることがある。
pm11_1.gif
pm11_2.gif

設問1

プログラム中の に入れる正しい答えを,解答群の中から選べ。
a に関する解答群
  • getInstance()
  • INSTANCE
  • new Notifier()
  • Notifier()
  • Notifier.class
  • this
b,c に関する解答群
  • device,devices
  • device,messageList
  • device,user
  • user,device
  • user,devices
  • user,messageList
d に関する解答群
  • extends
  • implements
  • requires
  • throw
  • throws
  • uses
e に関する解答群
  • device
  • device.getName()
  • name
  • Tester.this.name
  • this.name
  • user
解答選択欄
  • a:
  • b:
  • c:
  • d:
  • e:
  • a=
  • b=
  • c=
  • d=
  • e=

解説

aについて〕
Notifier クラスのメソッド getInstance の戻り値を答える問題です。
メソッドの宣言部から、戻り値の型は Notifier です。また、メソッド名から、戻り値は Notifier クラスのインスタンスであると推察されます。

〔プログラムの説明〕に、「クラス Notifier は,携帯端末の管理や通知メッセージの配信などを行う。Notifier のインスタンスは,シングルトン(Java仮想計算機内で唯一の存在)である。」と書かれていることから、Notifier クラスのインスタンスはプログラム中に一つだけしか存在してはいけません(newは一度しか使いません)。

〔プログラム3〕Notifier クラスの冒頭で、Notifier クラスのインスタンスが
private static final INSTSANCE = new Notifier()
と定義されています。final は定数を表す修飾子です。これをメソッド getInstance の戻り値として用いるのが適切です。

a=イ:INSTANCE
  • getInstance() はメソッド名です。設問で問われているメソッド以外で、同名のメソッドは Notifier クラス内に存在しないため、メソッド getInstance が自分自身を呼び出すことになり不適切です。
  • 正しい。
  • new を使って新たに Notifier クラスのインスタンスを生成する処理で、メソッド getInstance を呼び出すたびにインスタンスを新しく作り直すことになります。Notifier クラスのインスタンスはすでに定数 INSTANSE として生成されており、プログラム中に一つだけしか存在してはいけないという条件から、不適切です。
  • クラス名を名前に持つメソッド Notifier はコンストラクタなので、 new とともに使います。よって構文上不適切です。
  • インスタンスを返す記述ではないので不適切です。
  • メソッド getInstance は static で定義されているので、ここで this を使うことはできません。
bについて〕
メソッド register 内で、devices == null だった場合の処理に関する問題です。

〔プログラムの説明〕に、「メソッド register は,引数で指定された利用者名とその携帯端末名を登録する。指定された利用者名に対応する携帯端末名が既に登録されている場合は,その利用者名に対応する携帯端末名として追加登録する。」と書かれていることから、register は userMobileDevices に利用者名とその携帯端末名を登録するメソッドとわかります。

userMobileDevices は下図のような構造でデータが格納される変数です。
pm11_5.gif
devices は userMobileDevices.get(user) で定義されているので、devices == null とは、引数で渡した user に対応するデータが userMobileDevices 内に存在しないときだと考えられます。

よって、put の中身は、利用者 user と直前で生成している端末の空リスト devices が適切です。上図で示したように、端末は単数の device ではなく リスト devices であることに注意してください。

b=オ:user, devices

cについて〕
メソッド send 内で、messageList == null だった場合の処理に関する問題です。

〔プログラムの説明〕に、「メソッド send は,引数で指定された利用者名で登録されている各携帯端末に,引数で指定された文字列を通知メッセージとして配信する。携帯端末に対して未配信の通知メッセージがある場合,引数のメッセージを未配信のメッセージリストに追加する。」と書かれていることから、send は messagesToDeliver に利用者名とその携帯端末名を登録するメソッドとわかります。

messagesToDeliver は下図のような構造でデータが格納される変数です。
pm11_6.gif
messageList は messagesToDeliver.get(device) で定義されているので、messageList == null とは、引数で渡した device に対応するデータが messagesToDeliver 内に存在しないときだと考えられます。

よって put の中身は、端末 device と直前で生成しているメッセージの空リスト messageList が適切です。

c=イ:device, messageList

dについて〕
メソッドの宣言における、例外(○○○Exception)の記述に関する問題で、例外名の前に throws を記述します。throws には、この例外はこのメソッド内で処理せず、呼び出し元のメソッドで処理するという意味があります。

他の選択肢は全て構文上不適切です。なお、エ:throw はメソッド内で強制的に例外を発生させるときに使います。

d=オ:throws

eについて〕
標準出力に関する問題です。図1 メソッド main の実行結果の例を見ると、
phone: [You have a message.]
tablet: [You have a message.]
Terminating Taro's tablet
Terminating Taro's phone
となっており、上2つ、下2つはそれぞれ同じ処理によって出力されると考えられます。空欄部分は上2つのメッセージに該当すると考えられ、phone や tablet という端末名が入ります。よって、createUserMobileDevice の引数であり、登録端末名を保持する name を指定することになります。

e=ウ:name
  • 空欄は変数 device を宣言する途中の部分であり、device をここで使うことはできません。「->」はアロー演算子で、次の行まで device を宣言する記述は続いていることに注意してください。
  • 「ア」と同じ理由で不適切です。
  • 正しい。
  • メソッド createUserMobileDevice は static で定義されているので、ここで this を使うことはできません。
  • 「エ」と同じ理由で不適切です。
  • 端末名ではなく利用者名が出力されてしまうため不適切です。

設問2

プログラム4のクラス Tester において,メソッド main の/*α*/を図2の2行で置き換えて実行したとき,この2行に対するプログラムの動作に関する記述として,正しい答えを,解答群の中から選べ。
pm11_3.gif
解答群
  • "phone:[You have 2 messages.]"だけを出力する。
  • "tablet:[You have 2 messages.]" だけを出力する。
  • メソッド loopForMessages で,NullPointerException が発生する。
  • メソッド send で,NullPointerException が発生する。
  • 利用者名 Taro が登録されていないので,メソッド send は何もしないで終了する。
  • 利用者名 Taro は登録されているが,利用者名 Taro の携帯端末が何も登録されていないので,メソッド send は何もしないで終了する。
解答選択欄
  •  
  •  

解説

notifier.shutdown() を実行したあとで、notifier.send() を実行するとどうなるかが問われています。

先に解答群を確認すると、「ア」と「イ」は phone と tablet について同じことを言っています。プログラム内でどちらか一方だけ処理が行われるような記述はないので、不自然な選択肢です。そこで、まずはこの2つは除外して考えます。

残る4つの選択肢ですが、「ウ」と「エ」は NullPointException が発生するという内容が、それぞれ発生する場所が異なります。「オ」と「カ」はメソッド send が何もしないで終了するところは一緒ですが、その理由が異なります。

NullPointException が発生する状況として多いのが、メソッドを持つオブジェクトが null である場合です。本問の場合、notifier.shutdown() の処理内で、オブジェクトを null にするような処理があると、NullPointException が発生する可能性があると考えられます。

〔プログラムの説明〕でメソッド shutdown は、「メソッド shutdown は,通知システムを停止する。未配信の全メッセージ,全利用者名及び全携帯端末名の登録情報を削除し,登録されている全携帯端末の待ち受け状態を解除する。」と書かれており、オブジェクトに登録されているデータの中身を削除するのであり、オブジェクト自体を null にはしないと考えられます。よって、「ウ」と「エ」は正答ではないと判断できます。そして、また、利用者名、携帯端末の両方が削除されることがわかるので「カ」も除外できます。

∴オ:利用者名 Taro が登録されていないので,メソッド send は何もしないで終了する。
  • 前述で説明した通り、shutdown の処理が行われているため、send でメッセージを登録することができません。よって不適切です。
  • 「ア」と同じ理由で不適切です。
  • メソッド実行時に、userMobileDevices または messagesToDeliver が null のときにこのような例外が発生すると考えられます。これらは Notifier クラスの冒頭で定義された定数(finalで宣言されている)であり、その後 null を代入することはできません。よって不適切です
  • 「ウ」と同じ理由で不適切です。
  • 正しい。
  • 〔プログラムの説明〕の内容から、createUserDevice メソッドは利用者名と携帯端末をセットで登録し、shutdown メソッドはそれらをセットで削除することが分かります。よって、利用者名のみが登録されているという状況にはなり得ないため、不適切です。

Pagetop