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 obj = /*[A]*/ } } interface MyInterface{ public abstract void myMethod(Object val); }
問./[A]/の部分に入れてコンパイルしてもコンパイルエラーにならないものを以下の選択肢からすべて選びなさい。
選択肢
1.
new MyInterface(){ public void myMethod(Object val){ } };
2.
new MyInterface(){ public void myMethod(){ } };
3.
(Object val) -> { };
4.
(Object obj) -> { };
5.
(t) -> { };
解答
1,3,5
解説
今回は選択肢1と2が匿名クラス、選択肢3と4と5がラムダ式による記述になっている。
実装のもととなっているインタフェースは次のように定義されている。
interface MyInterface{ public abstract void myMethod(Object val); }
このインタフェースには抽象メソッドとしてmyMethod()メソッドが定義されている。
Sample.javaの中でMyInterface型の変数objを宣言する箇所は以下のようになっている。
MyInterface obj = /*[A]*/
5つの選択肢に共通して処理内容が書かれていないが、myMethod()メソッドでは戻り値にvoid型が指定されている。
{}の中に処理内容が何も書かれていないが、処理内容が無いことは今回はコンパイルエラーの理由にはならない。
匿名クラスでインタフェースの実装を行う場合は次のように行う。
new インタフェース名(){ //メソッドのオーバーライド };
1.
new MyInterface(){ public void myMethod(Object val) { } };
匿名クラスの実装方法に従っている。メソッドのオーバーライドも特に問題はない。
そのためコンパイルエラーとはならない。
2.
new MyInterface(){ public void myMethod() { } };
これも匿名クラスの実装方法に従っている。しかし、もとのインタフェースではmyMethod()メソッドの引数にObject型の引数が指定されているが、選択肢2では引数が無く実装として正しくない。
よってコンパイルエラー。
ラムダ式を使って実装行う場合は次のように行う。
(抽象メソッドの引数の型名 引数名) -> { //抽象メソッドの処理 };
3.
(Object val) -> { };
ラムダ式を使用した実装方法に従っている。
そのためコンパイルエラーにならない。
4.
(Object obj) -> { };
選択肢3によく似ている。引数の変数名だけが異なっている。
左辺を見るとMyInterface型の変数を宣言する際に変数名をobjにしているが、ラムダ式の引数名の宣言でもobjという変数名を使用している。そのため、変数名の重複が起こる。
よってコンパイルエラー。
5.
(t) -> { };
一見するとおかしな書き方になっているようにも見える。しかし、ラムダ式を使用する際には、すべての引数のデータ型を省略しても良い※。
今回は引数が1つ必要で、そのデータ型はObject型となっているが、これを省略している。また、引数名はvalとなっているが、引数名は変更しても良い。よって引数名が t となっている部分も問題ない。
そのためコンパイルエラーにならない。
※引数が2つ以上ある場合、省略したものと省略しないものを混ぜてはいけない。以下のサンプルを要確認。
public class Sample{ public static void main(String[] args){ MyInterface obj = (Object val1, val2)->{ //コンパイルエラー }; /* MyInterface obj = (Object val1, Object val2) -> { //OK }; */ /* MyInterface obj = (val1, val2) -> { //OK }; */ } } interface MyInterface{ public abstract void myMethod(Object val1, Object val2); }
ラムダ式の省略については下記の表を参照。
ラムダ式の省略可否一覧
省略個所 | 省略の可否 | 注意点 |
---|---|---|
引数のデータ型 | ○ 省略可能 | ・データ型が省略されている引数とされていない引数が混ざっている場合は省略できない。
※省略する場合は必ずすべての引数のデータ型を省略すること。 |
引数の( ) | △ 省略可能 ※ 条件付き |
・引数なしの場合は省略できない。
・引数が2つ以上の場合は省略できない。 ・ 引数のデータ型が書いてあると( )は省略できない。
※引数が1つで、データ型が省略されている時のみ省略可能。 |
処理の{ } | △ 省略可能 ※ 条件付き |
・処理が2行以上にわたる場合は省略できない。
・処理が ; しかない場合は省略できない。(プログラムの構造がおかしくなるため) ・戻り値がある場合、return キーワードが書いてあると省略できない。
※処理が1行しかない場合は省略可能。戻り値がある場合は下記参照。 |
(戻り値がある場合) return キーワード |
△ 省略可能 ※ 条件付き |
・return 文以外の処理もある場合は省略できない。
・{ } が書いてあると省略できない。
※ 処理内容がreturn 文のみで、{ }も省略する場合のみ省略可能。その場合、処理内容には戻り値のみが書かれる。 ※ 戻り値そのものがなくなるわけではないので注意。 |
引数名 | × 省略できない | ・引数名は省略できない。
※ただし、引数名はもとのインタフェースと異なっていても良い。ローカル変数のスコープに注意して変数名を定義すること。 |
オススメ!!→ 過去のjava 8 の問題はこちら