戦国IT - 情報処理技術者試験の過去問対策サイト
ブログお知らせお問い合わせ料金プラン

基本情報技術者 2018年 春期 午後 問11


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

〔プログラムの説明〕  A君は、先輩エンジニアであるBさんの指導の下で、表現式(以下、式という)を構築するためのライブラリの作成を進めている。ライブラリはAPIを提供する。  まず、次のインタフェース及びクラスをパッケージcom.example.exprに作成した。   (1) インタフェースExpressionは、式を表す。すなわち、Expressionを実装するクラスは、型としての式を表す。  ① メソッドevaluateは、式を評価した結果を型intで返す。 (2) クラスConstantは、定数を式(型Expression)として表す。  ① コンストラクタは、引数で与えられた型intの値を表す定数を生成する。  ② メソッドevaluateは、この定数の値を返す。  ③ メソッドtoStringは、この定数の値を文字列として返す。 (3) クラスAdditionは、加算を式(型Expression)として表す。  ① コンストラクタは、加算式を生成する。加算式a + bにおいて、演算子+の左側aの部分を左側の式、右側bの部分を右側の式とし、それぞれ引数left及び引数rightで指定する。いずれかの引数がnullのときは、NullPointerExceptionを投げる。  ② メソッドevaluateは、左側の式を評価した値に右側の式を評価した値を加え、その値を返す。  ③ メソッドtoStringは、この加算式を表す文字列を返す。
基本情報技術者試験(平成30年 午後 問11 プログラム1)
基本情報技術者試験(平成30年 午後 問11 プログラム2)
基本情報技術者試験(平成30年 午後 問11 プログラム3)

設問1:

問題文を見る
 A君は、クラスConstant及びAdditionをAPIとして呼び出すテストをするために、クラスTestをパッケージcom.example.testに作成して実行したところ、図1の出力結果を得た。プログラム4中のに入れる正しい答えを、解答群の中から選べ。
基本情報技術者試験(平成30年 午後 問11 図1)
基本情報技術者試験(平成30年 午後 問11 プログラム4)
aに関する解答群  ア:com.example.expr  イ:com.example.test  ウ:static com.example.expr  エ:static com.example.test   bに関する解答群  ア:2, 5  イ:5, 2  ウ:five  エ:five, two  オ:two  カ:two, five   c, dに関する解答群  ア:add  イ:add.evaluate()  ウ:five  エ:five.evaluate()  オ:two  カ:two + five  キ:two.evaluate()

模範解答

a:ア、b:カ、c:ア、d:イ

解説

解答の導き方

この問題では、図1の「(2 + 5) = 7」を表示するために、プログラム4の空欄を埋めます。空欄ごとに、必要な情報を確認していきます。
  1. a:クラスを置いたパッケージを指定します
    プログラム1〜3には、それぞれ「package com.example.expr;」とあります。これは、Expression、Constant、Additionの各クラスが、com.example.exprというパッケージ(関連するクラスをまとめる名前空間)に置かれているという意味です。
    プログラム4では、これらのクラスを使うためにimport文で指定します。importの後にはクラスを置いたパッケージ名が必要なので、aには「com.example.expr」が入ります。staticは付けません。ここで読み込むのは、クラスに属する静的な機能ではなく、クラスそのものだからです。
  2. b:加算式の左側と右側を指定します
    プログラム4では、twoはConstant(2)、fiveはConstant(5)として作られています。つまり、twoは値2を表す式、fiveは値5を表す式です。
    Additionの説明には、引数leftが加算式の左側、引数rightが右側とあります。図1では「(2 + 5)」と表示されているため、左側にtwo、右側にfiveを渡します。したがって、bには「two, five」が入ります。
    2や5を直接渡すのではなく、twoやfiveを渡す点にも注意してください。Additionのコンストラクタが受け取るのは、整数ではなくExpression型の式です。
  3. c:加算式の形を表示する値を指定します
    ConstantとAdditionは、どちらもExpressionを実装しています。Expressionは式を表す型で、Additionの変数addには、2と5を加算する式が入っています。
    ConstantのtoStringは定数の値を文字列にし、AdditionのtoStringは左右の式を使って加算式を表す文字列を作ります。そのため、文字列連結の左側にはaddを指定すれば、加算式が「(2 + 5)」と表示されます。したがって、cにはaddが入ります。
  4. d:計算結果を表示する値を指定します
    Additionのevaluateは、左側の式の評価結果と右側の式の評価結果を足します。two.evaluate()は2、five.evaluate()は5を返すので、add.evaluate()は2 + 5、つまり7を返します。
    したがって、dにはadd.evaluate()が入ります。これにより、図1のように加算式と計算結果を並べて表示できます。

誤りやすいポイント

  • 引数の順番を逆にしないこと
    Additionでは、最初の引数が左側、2番目の引数が右側です。図1の「(2 + 5)」に合わせるには、twoを先に、fiveを後に渡します。
  • 式の表示と評価結果を区別すること
    addは式そのものを表します。add.evaluate()は、その式を計算した結果です。式の形を表示する場所にはadd、答えを表示する場所にはadd.evaluate()を使います。
  • 変数の名前ではなく、変数が表す内容を見ること
    twoとfiveは名前だけでなく、それぞれConstant(2)、Constant(5)として作られています。どちらを左側・右側に置くかは、表示したい式の順番から判断します。

FAQ

Q: cにaddを指定すると、なぜ「(2 + 5)」と表示されるのですか?
A: addはAdditionのオブジェクト(クラスを基に作られたもの)で、AdditionのtoStringが加算式を文字列にします。文字列とaddを連結するとき、その文字列化された内容が使われます。
Q: dにaddではなくadd.evaluate()を指定するのはなぜですか?
A: addは計算式そのものを表すからです。計算した値を表示するには、式を評価するevaluateを呼び出します。
Q: bに2, 5を指定できないのはなぜですか?
A: AdditionのコンストラクタはExpression型の引数を受け取ります。整数の2や5ではなく、定数を式として表すtwoやfiveを渡します。

関連キーワード: パッケージ、import文、インタフェース、コンストラクタ、文字列連結、toStringメソッド

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

 次の記述中のに入れる正しい答えを、解答群の中から選べ。    A君は、これまでに作成したプログラムをBさんに見てもらったところ、次のアドバイスを受けた。  “乗除算などの式を実装するクラスを追加する前に、上位クラスを導入して二項演算を表すクラスを簡単に実装できるようにすべきである。また、アプリケーションが必要とする全ての二項演算をライブラリで用意するのは一般に難しいので、パッケージ外でも二項演算がそのクラスの下位クラスとして簡単に実装できるようにすべきである。”  そこで、A君は、次の仕様の抽象クラスをライブラリに追加した。   (1) 抽象クラスBinaryOperatorExpressionは、二項演算子を使用する式(以下、二項演算式という)を表す。  ① コンストラクタは、二項演算式を生成する。二項演算式a OP bにおいて、二項演算子OPの左側aの部分を左側の式、右側bの部分を右側の式とし、それぞれ引数left及び引数rightで指定する。いずれかの引数がnullのときは、NullPointerExceptionを投げる。  ② メソッドgetLeft及びgetRightは、それぞれ左側の式及び右側の式を返す。  ③ 抽象メソッドgetOperatorは、この二項演算式の演算子を文字列で返す。  ④ メソッドtoStringは、この二項演算式を表す文字列を返す。    このクラスをBさんに見てもらったところ、“ライブラリで用意されたAPIを呼び出すアプリケーションで二項演算式を表すクラスの実装に使えるようにすることが目的なので、ようにするために、コンストラクタとメソッドgetLeft、getRight及びgetOperatorはpublicではなくprotectedにすべきである”という指摘を受け、その修正をしてプログラム5を作成した。
基本情報技術者試験(平成30年 午後 問11 プログラム5)
解答群  ア:下位クラスを実装するクラスだけで使える  イ:上位クラスの実装が下位クラスで改変されない  ウ:通常のアプリケーションがどのパッケージからでも呼び出せる  エ:パッケージcom.example.expr内の下位クラスだけで使える

模範解答

ア

解説

解答の導き方

この設問では、二項演算を表すクラスを作るときに、上位クラスのどの機能を下位クラスから使えるようにするかを考えます。上位クラスは共通部分をまとめた親のクラス、下位クラスはそこから具体的な機能を加える子のクラスです。
問題文には、ライブラリが用意していない二項演算も「パッケージ外」で実装できるようにしたい、とあります。つまり、ライブラリを使うアプリケーション側でも、BinaryOperatorExpressionを継承して独自の演算式を作れるようにする必要があります。パッケージとは、関連するクラスをまとめる単位です。
そのためには、下位クラスの実装に必要な次の機能を使えるようにします。
  • コンストラクタ:下位クラスのオブジェクトを作るときに、左右の式を上位クラスに渡します。
  • getLeftとgetRight:下位クラスから、左右の式を取得します。
  • getOperator:下位クラスで演算子を定義します。
一方、これらをpublicにすると、下位クラスではない通常のクラスからも呼び出せます。publicは、どのクラスからも利用できる指定だからです。下位クラスの実装に必要な機能として利用範囲を限定するには、protectedが適しています。protectedは、別のパッケージにある下位クラスからも利用できます。
したがって、空欄には「下位クラスを実装するクラスだけで使える」という内容のアが入ります。
なお、Javaのprotectedは、同じパッケージ内のクラスからも利用できます。選択肢のアは、問題文にある「パッケージ外でも下位クラスを実装できるようにする」という目的に着目したものです。

誤りやすいポイント

  • protectedを「同じパッケージ内だけで使える」と考えないようにします。別のパッケージにある下位クラスからも利用できます。
  • publicとprotectedの違いは、利用できる範囲です。publicは広く公開し、protectedは主に下位クラスから使う機能を公開します。
  • この設問は、演算子の計算方法ではなく、下位クラスから機能を使えるようにするためのアクセス範囲を問うています。
  • 抽象クラスは直接オブジェクトを作れませんが、下位クラスのオブジェクトを初期化するために、上位クラスのコンストラクタは必要です。

FAQ

Q: getLeftとgetRightをprotectedにするのはなぜですか?
A: 下位クラスが左右の式を取り出し、評価や独自の処理に使うためです。通常のアプリケーションから自由に呼び出すための機能ではありません。
Q: getOperatorが抽象メソッドなのはなぜですか?
A: 加算や減算のように、演算子の種類は下位クラスごとに異なるためです。上位クラスは共通部分を用意し、具体的な演算子は下位クラスに決めさせます。
Q: protectedは、下位クラス以外から絶対に使えませんか?
A: いいえ。同じパッケージ内のクラスからも使えます。この設問では、パッケージ外の下位クラスにも機能を使わせる点が重要です。

関連キーワード: アクセス修飾子、protected、public、継承、抽象クラス

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

 次の記述中のに入れる正しい答えを、解答群の中から選べ。ここで、プログラム6中のaには、設問1の正しい答えが入っているものとする。    プログラム6は、ライブラリのパッケージ外で二項演算式を実装するテストとして、減算式を表すクラスSubtractionを実装したものである。
基本情報技術者試験(平成30年 午後 問11 プログラム6)
 プログラム6をテストするために、プログラム4のメソッドmainの/* α */の行を図2に示す行に置き換えて実行したところ、図1に示した出力結果に加え、出力結果“”を得た。
基本情報技術者試験(平成30年 午後 問11 図2)
解答群  ア:((2 + 5) - (2 - 5))  イ:((7) - (-3))  ウ:(2 + 5 - 2 - 5)  エ:(2 + 5) - (2 - 5)  オ:0  カ:10

模範解答

ア

解説

解答の導き方

ここで問われているのは、図2の行を実行したときに表示される文字列です。数値としての計算結果ではなく、式の形がどう表示されるかを考えます。
まず、プログラム6の「Subtraction」は「BinaryOperatorExpression」を継承しています。継承とは、元となるクラスの処理や性質を引き継ぐ仕組みです。減算の記号は「getOperator」が返す「-」で、左右の式はコンストラクタに渡した値です。
図2の行では、外側の減算式の左側に「add」、右側に新しい減算式を渡しています。
  • 左側の「add」は、図1の出力から「(2 + 5)」という式です。
  • 右側の減算式は、「two」と「five」を使うので「(2 - 5)」という式です。
「println」に式のオブジェクトを渡すと、表示用の文字列を作るために「toString」が呼び出されます。BinaryOperatorExpressionの文字列化では、左右の式と演算子を括弧で囲んで表示します。左右の式もそれぞれ文字列に変換されるため、外側の式は「((2 + 5) - (2 - 5))」になります。
このように、式の構造を保った文字列になるので、該当するのは「ア」です。
数値として計算すると、左側は 、右側は なので、全体は です。ただし、この行は式の「evaluate」を呼び出していません。したがって、数値の「10」ではなく、式を表す文字列が表示されます。
なお、「a」に入るパッケージ名は、Expressionなどが置かれている「com.example.expr」です。

誤りやすいポイント

  • 「println」に渡した式が自動的に計算されると思い込まないようにします。計算結果を得るには、「evaluate」を呼び出す必要があります。
  • 「10」は減算式を評価した結果ですが、表示されるのは式の構造を表す文字列です。
  • 左右の式にも括弧があるため、外側の括弧と合わせて「((2 + 5) - (2 - 5))」となります。括弧を省いた形にはなりません。

FAQ

Q: なぜ「println」は「toString」を呼び出すのですか?
A: 式のオブジェクトそのものを文字として表示するため、表示用の文字列を作る処理が必要だからです。この問題では「toString」が式の形を文字列にします。
Q: 数値の結果である「10」を表示したい場合は、どうすればよいですか?
A: 式に対して「evaluate」を呼び出し、その戻り値を表示します。この問題の行では「evaluate」を呼び出していないため、数値ではなく式の形が表示されます。
Q: 「(2 - 5)」が「-3」と表示されないのはなぜですか?
A: 「toString」は式を文字列として表し、「evaluate」は式を計算します。表示に使われるのは前者なので、「(2 - 5)」のままです。

関連キーワード: クラス継承、オブジェクト、toString、式の評価、インタフェース

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

 次の記述中のに入れる正しい答えを、解答群の中から選べ。    Bさんから、更に次の指摘を受けた。  “オブジェクトの等価についての考慮も必要である。例えば、を評価すると、二つのインスタンスが表す値が等しいのでtrueになるべきだが、今のクラスConstantの実装ではfalseになる。”   解答群  ア:new Constant(9) == new Constant(9)  イ:new Constant(9).equals(new Constant(9))  ウ:new Constant(9).evaluate() == new Constant(9).evaluate()  エ:new Constant(9).evaluate().equals(new Constant(9).evaluate())

模範解答

イ

解説

解答の導き方

この設問では、値が同じ二つの定数を比べたとき、どの書き方なら現在の実装では等しいと判定されないかを考えます。
まず、new Constant(9) は、値が9のConstantのインスタンス(クラスを基に作られた個々のオブジェクト)を新しく作ります。式の中で二回書かれているので、別々のインスタンスが二つ作られます。
問題文には、ConstantのメソッドとしてevaluateとtoStringは示されていますが、equalsはありません。そのため、equalsを呼び出すと、Javaの基本機能として用意されているObjectのequalsが使われます。このequalsは、二つのインスタンスが同じ値を持つかではなく、同一のインスタンスかどうかを判定します。
選択肢を順に確認します。
  • アの「new Constant(9) == new Constant(9)」は、二つのインスタンスが同一かどうかを比較します。別々に作られたインスタンスなので、falseになります。ただし、これはequalsによる比較ではありません。
  • イの「new Constant(9).equals(new Constant(9))」は、二つのConstantのインスタンスに対してequalsを呼び出します。現在の実装では同じ値かどうかを調べる処理がないため、別々のインスタンスは等しくないと判定され、falseになります。設問の「二つのインスタンスが表す値が等しいのでtrueになるべきだが、今のクラスConstantの実装ではfalseになる」という状況に当てはまります。
  • ウの「new Constant(9).evaluate() == new Constant(9).evaluate()」は、二つのインスタンスそのものではなく、evaluateで取り出した値を比較します。どちらも9なので、結果はtrueです。
  • エの「new Constant(9).evaluate().equals(new Constant(9).evaluate())」は、evaluateが返す型intの値にequalsを呼び出そうとしています。intは数値を表す基本型で、メソッドを呼び出せないため、この書き方は使えません。
したがって、設問の状況を表すのはイです。値が等しいインスタンスをequalsでもtrueと判定させるには、Constantに値を比較するequalsを実装する必要があります。

誤りやすいポイント

  • ==とequalsは、どちらも「等しいか」を調べますが、現在のConstantでは、==はインスタンスが同一かどうかを比較し、equalsも同一のインスタンスかどうかを判定します。
  • evaluate()を使うと、比較対象はインスタンスではなく、インスタンスが表す値になります。二つの値が9なら、ウはtrueです。
  • intは基本型です。intの値にequalsを呼び出すことはできないため、エは等しいかどうかを調べる式として成立しません。

FAQ

Q: イでは、なぜ二つの値が同じなのにfalseになるのですか?
A: 現在のConstantには、値を比べるequalsがありません。Javaから引き継いだequalsは、二つのインスタンスが同一かどうかを判定するため、別々に作られたインスタンス同士ではfalseになります。
Q: ウがtrueなら、設問の条件を満たしているのではありませんか?
A: ウは、二つのインスタンスの値を取り出して比較しています。設問は、二つのインスタンスに対してequalsを使ったときの動作を尋ねています。そのため、ウは該当しません。
Q: equalsで値の等しさを判定するには、どうすればよいですか?
A: Constantにequalsを実装し、二つのインスタンスが持つvalueを比較します。そうすれば、値が同じインスタンス同士をtrueと判定できます。

関連キーワード: equalsメソッド、オブジェクト、参照比較、値比較、オーバーライド

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

戦国ITクイズ機能

\ せっかくなら /

基本情報技術者を
クイズ形式で学習しませんか?

クイズ画面へ遷移する→

すぐに利用可能!

©︎2026 情報処理技術者試験対策アプリ

このサイトについてブログプライバシーポリシー利用規約特商法表記開発者について