java練習問題
java練習問題
動作環境と問題内容について
javaの練習問題です。 出題範囲はjava 8 で追加された範囲を中心とします。難易度は Java SE 8 Programmer I の試験と同程度を想定しています。
実行環境は以下の通りです。
PC:MacBook Pro 2011early 15inch
OS:Windows 8.1(デュアルブート) 64bit版
メモリ:16GB(8GB x 2)
CPU:Core i7-2635QM 2.00GHz
javaのバージョン:java 8 Update102
※問題文に書いてあるプログラムを実行する際は自己責任で実行してください。
問題
次のプログラムを作成した。コンパイル、実行に関して以下の問いに答えなさい。
プログラム(Sample.java)
public class Sample{ public static void main(String[] args){ MyInterface<String> obj = /*[A]*/ } } interface MyInterface<T>{ public abstract void myMethod(T val); }
問.[A]の部分に入れてコンパイルしてもコンパイルエラーにならないものを以下の選択肢からすべて選びなさい。
選択肢
1.
new MyInterface<String>(){ public void myMethod(String val) { } };
2.
new MyInterface<String>(){ public String myMethod(String val) { return "Hello"; } };
3.
(String t) -> { };
4.
(Object t) -> { };
解答
1,3
解説
今回は選択肢1と2が匿名クラス、選択肢3と4がラムダ式による記述になっている。
実装のもととなっているインタフェースは次のように定義されている。
interface MyInterface<T>{ public abstract void myMethod(T val); }
このインタフェースには抽象メソッドとしてmyMethod()メソッドが定義されている。また、クラスやメソッドの定義にジェネリクスが利用されている。
Sample.javaの中でMyInterface型の変数objを宣言する箇所ではジェネリクスにStringを指定している。
MyInterface<String> obj = /*[A]*/
今回はこのジェネリクスに注意した上で実装しなければならない。
また、1,3,4の選択肢に共通して処理内容が書かれていないが、myMethod()メソッドでは戻り値にvoid型が指定されている。{}の中に処理内容が何も書かれていないくても今回はコンパイルエラーの理由にはならない。
匿名クラスでインタフェースの実装を行う場合は次のように行う。
new インタフェース名(){ //メソッドのオーバーライド };
1.
new MyInterface<String>(){ public void myMethod(String val) { } };
匿名クラスの実装方法に従っている。また、ジェネリクスは右辺のクラス宣言new MyInterface<String>となっており、myMethod()メソッドでも同じStringを指定している。
よってコンパイルエラーとはならない。
2.
new MyInterface<String>(){ public String myMethod(String val) { return "Hello"; } };
これも匿名クラスの実装方法に従っている。しかし、もとのインタフェースではmyMethod()メソッドの戻り値がvoidとなっているが、選択肢2では戻り値がStringとなっている。
これではオーバーライドにならず、匿名クラス内で抽象メソッドが実装されていないことになる。
よってコンパイルエラー。
ラムダ式を使って実装行う場合は次のように行う。
(抽象メソッドの引数の型名 引数名) -> { //抽象メソッドの処理 };
3.
(String t) -> { };
ラムダ式を使用した実装方法に従っている。
そのためコンパイルエラーにならない。
4.
(Object t) -> { };
ラムダ式を使用した実装方法に従っているように思える。
変数objの宣言時にはジェネリクスでString型を指定しているため、抽象メソッドの引数のデータ型はString型と推定される。
しかし、ラムダ式を利用したMyInterfaceインタフェースの実装部分では、抽象メソッドの引数のデータ型にObject型を指定している。
よって矛盾が生じるため、コンパイルエラーとなる。
ラムダ式の省略については以下も参照すること。
ラムダ式の省略可否一覧
省略個所 | 省略の可否 | 注意点 |
---|---|---|
引数のデータ型 | ○ 省略可能 | ・データ型が省略されている引数とされていない引数が混ざっている場合は省略できない。
※省略する場合は必ずすべての引数のデータ型を省略すること。 |
引数の( ) | △ 省略可能 ※ 条件付き |
・引数なしの場合は省略できない。
・引数が2つ以上の場合は省略できない。 ・ 引数のデータ型が書いてあると( )は省略できない。
※引数が1つで、データ型が省略されている時のみ省略可能。 |
処理の{ } | △ 省略可能 ※ 条件付き |
・処理が2行以上にわたる場合は省略できない。
・処理が ; しかない場合は省略できない。(プログラムの構造がおかしくなるため) ・戻り値がある場合、return キーワードが書いてあると省略できない。
※処理が1行しかない場合は省略可能。戻り値がある場合は下記参照。 |
(戻り値がある場合) return キーワード |
△ 省略可能 ※ 条件付き |
・return 文以外の処理もある場合は省略できない。
・{ } が書いてあると省略できない。
※ 処理内容がreturn 文のみで、{ }も省略する場合のみ省略可能。その場合、処理内容には戻り値のみが書かれる。 ※ 戻り値そのものがなくなるわけではないので注意。 |
引数名 | × 省略できない | ・引数名は省略できない。
※ただし、引数名はもとのインタフェースと異なっていても良い。ローカル変数のスコープに注意して変数名を定義すること。 |
オススメ!!→ 過去のjava 8 の問題はこちら