41:次のコード断片のうちコンパイルエラーが生じないものを2個選べ。
A:import java.util.ArrayList;
package a;
public class A{ArrayList i=new ArrayList();}
B:package a;
import java.util.*;
public class A{Collection i;List j;ArrayList k;}
C:import java.util.ArrayList;
public class A{List i=new ArrayList();}
D:package a;
import java.util.List;
import java.util.Collection;
public interface A{static List i=List.of();
static Collection<Character> j=new java.util.ArrayList();}
E:import java.util.ArrayList;
package a;
import java.util.List;
public record A{static java.util.Collection i; static List<Integer> j=new ArrayList();}
F:import java.util.*;
public abstract class A{List<int>i;}
正解を確認する
コンパイルエラーが生じないコード B: 正しいファイル構造:package 宣言が import 宣言より前にあり、Javaの規則に従っています。 型の解決:import java.util.*; により、Collection、List、ArrayList の型がすべて正しく解決されています。 文法:クラスのフィールド宣言として完全に正しく、初期化されていないフィールドは null で初期化されます。 D: 正しいファイル構造:package 宣言の後に import 宣言が続く、正しい構造です。 インターフェースのフィールド:インターフェースのフィールドは暗黙的に public static final となるため、宣言時に初期化が必要です。static List i = List.of(); は、不変リストで初期化されており有効です。 static Collectionj = new java.util.ArrayList(); も、インスタンスで初期化されており有効です。 コンパイルエラーが生じるコードとその理由 A:エラー理由:宣言の順序誤り。package 宣言は、すべての import 宣言より前に記述しなければなりません。 C:エラー理由:ArrayListはimportされていますが、Listがimportされていないためです。 E: エラー理由:宣言の順序誤り。package 宣言が import 宣言より後に記述されているためです。 (ただし、レコードの静的フィールド宣言自体は有効です。) F:エラー理由:ジェネリクスの誤用。ジェネリクス(List<...>)の型引数には、プリミティブ型(int)を使用できません。必ずラッパークラス(Integer)を使用する必要があります。
42:次のコードをコンパイル、実行したときの結果として正しいものを選びなさい。
public class Main {
static int i=2;static int j;
static boolean k;static String m;
static int[] l=new int[1];
public static void main(String[] k) {
if(i())System.out.println(j());
else System.out.println(j().toUpperCase());
}
static boolean i() {
try {
i/=j;
}catch(ArithmeticException ae) {
return k;
}catch(RuntimeException re) {
return !k;
}finally {k=true;}
return k;
}
static String j() {
try {
l[1]/=i;
}catch(ArrayIndexOutOfBoundsException iobe) {
return m;
}finally {m="hi";}
return m;
}
}
A:hi
B:HI
C:NULL
D:null
E:コンパイルエラーが生じる
F:実行時に例外がスローされる
正解を確認する
1. i() メソッドの実行(if 文の条件)
i() メソッド内の try ブロックでゼロ除算が発生し、ArithmeticException がスローされます。
static boolean i() {
try {
i/=j; // 2 / 0 で ArithmeticException がスロー
} catch(ArithmeticException ae) {
return k; // k の現在の値 (false) が戻り値として一時保持される
} finally {
k=true; // k が true に更新される
}
// finally 実行後、保持されていた false が i() の戻り値となる
}
i() メソッドの戻り値は false です。
2. else ブロックの実行
if 文の条件が false のため、else ブロックが実行されます。
else System.out.println(j().toUpperCase());
3. j() メソッドの実行(引数の評価)
まず、j() メソッドが呼び出されます。
static String j() {
try {
l[1]/=i; // l は要素数 1 (インデックス 0 のみ) の配列。l[1] は ArrayIndexOutOfBoundsException
} catch(ArrayIndexOutOfBoundsException iobe) {
return m; // m の現在の値 (null) が戻り値として一時保持される
} finally {
m="hi"; // m が "hi" に更新される
}
// finally 実行後、保持されていた null が j() の戻り値となる
}
j() メソッドの戻り値は null です。
4. 最終的な例外の発生
main メソッドの実行は以下のようになります。
System.out.println(null.toUpperCase());
null である参照に対してインスタンスメソッドである toUpperCase() を呼び出そうとすると、NullPointerException が実行時にスローされ、プログラムは異常終了します。
43:次のコードに関する記述として正しいものを2個選びなさい。
public class M {
public static void main(String[] k) {
A a=new A(1,"2","3");
A b=new A(1,"2","3");
a.equals(b);//line a
a.hashCode();//line b
a.toString();//line c
a.i();//line d
}
public int i(){return 0;}
}
final record A(int i, String...j){}
A:line a~cではjava.lang.Object classのメソッドが実行される
B:line aはtrueを返す
C:line cはハッシュコードを返す
D:line dは0を返す
E:このコードはコンパイルエラーが生じる
F:このコードは実行時に例外がスローされる
G:aの作成時にレコードA内にprivate static finalなフィールドiが作られ1で初期化される。
H:bの作成時にレコードA内にprivate finalなフィールドj[]が作られ、”2″と”3″で初期化される。
正解を確認する
正しい記述
B:レコード A は、コンポーネントの値に基づいた equals() メソッドを自動生成します。a と b はどちらも A(1, "2", "3") という全く同じ値を持つインスタンスです。したがって、a.equals(b) はコンポーネントの値が全て等しいと判断し、true を返します。
H:レコードコンポーネント(String...j)は、暗黙的にインスタンスフィールドとして定義されます。可変長引数 (...) は、レコード内部では String[] 型のフィールドとして扱われます。レコードのコンポーネントフィールドは常に private final であり、インスタンス作成時(コンストラクタ実行時)に渡された値で初期化されます。b の作成時に渡された値は "2" と "3" です。
誤っている記述
A:レコード A は、Object の equals(), hashCode(), toString() をコンポーネントに基づいた実装で自動的にオーバーライドします。Object クラスの基底実装がそのまま実行されるわけではありません。
C:line c は a.toString() の呼び出しであり、レコードコンポーネントを含む文字列を返します。ハッシュコードを返すのは a.hashCode()(line b)です。
D:a.i(); は、A クラスの暗黙的に生成されたアクセサメソッド public int i() を呼び出します。これはコンポーネント i の値である 1 を返します。M クラス内に定義された public int i(){return 0;} メソッドとは無関係です。
G:レコードコンポーネントに対応するフィールドは private final のインスタンスフィールドとして生成されます。static(静的)ではありません。
44:次のコードをコンパイル、実行したときの結果として正しいものを選びなさい。
public class Main{
protected static int i;
public static void main(String[] args) {
Main[]i= {new Main(),new A(),null};
i[2]=count(i);
int k=0;
while(k<i.length) {
if(i[k] instanceof A)Main.i++;
k++;
}
System.out.println(Main.i);
}
static void a(Main j) {
if(j instanceof A)Main.i++;
else if(j instanceof Main)--i;
else Main.i+=2;
}
static Main count(Main[] i) {
for(Main j:i) {
a(j);
return Main.i>0?new A():new Main();
}
}
}
class A extends Main{
static void a(Main j) {
if(j instanceof A)i++;
else if(j instanceof Main)--Main.i;
else Main.i-=2;
}
}
A:0
B:1
C:2
D:3
E:コンパイルエラー
F:実行時に例外が生じる
正解を確認する
戻り値の型がvoid以外(この場合は Main)に設定されているメソッドは、どのような実行経路をたどっても必ず return 文に到達しなければなりません。 count メソッドでは、唯一の return 文が for-each ループの中にあります。もし、引数として渡された配列 i が空の配列(要素数が0)だった場合、この for-each ループは一度も実行されません。 その結果、プログラムの実行はループを素通りしてメソッドの終わりに到達してしまいますが、そこに return 文が存在しないため、「値を返さずにメソッドが終わってしまう可能性がある」とコンパイラが判断します。 これにより、「missing return statement」(return文がありません)というコンパイルエラーが発生します。そのため、このプログラムは実行ファイル(.classファイル)を生成できず、実行することができません。
45:次のコード断片のうちコンパイルエラーが生じないものを選びなさい。
A:try{Object i=null;i.toString();}catch(Exception i){}catch(RuntimeException j){}
B:try{String i=”1″;i.indexOf(“1”);}catch(StringIndexOutOfBoundsException |RuntimeException i){}
C:a:try{return;}finally{return;}
D:try{}catch(Throwable t){}finally{}finally{}
E:上記はすべて正しい
F:上記のいずれも正しくない
正解を確認する
A:これはコンパイルエラーになります。 Javaの try-catch 構文では、複数の catch ブロックを定義する場合、より具体的な例外(サブクラス)を先に記述し、より一般的な例外(スーパークラス)を後に記述する必要があります。 RuntimeException は Exception のサブクラス(子クラス)です。 このコードでは、スーパークラスである Exception を先に catch しているため、その後に記述された RuntimeException の catch ブロックには到達できません。そのため、「到達不可能なコード」としてエラーになります。 B:|(パイプ)で複数の例外を捕捉するマルチキャッチ構文では、RuntimeException とそのサブクラスである、StringIndexOutOfBoundsException のように、継承関係にある例外を同時に指定することはできません。 C:これはコンパイルエラーを生じません。a: はラベルであり、問題ありません。try ブロックと finally ブロックの両方に return; 文がある場合、finally ブロックの return; が実行されます。 D:これはコンパイルエラーになります。 一つの try ブロックに対して、finally ブロックは一つしか記述することができません。このコードでは finally が二つ連続しているため、構文エラーとなります。
46:次のコードをコンパイル、実行したときの結果として正しいものを選びなさい。
import java.util.ArrayList;
public class Main {
public static void main(String[] k) {
ArrayList i=new ArrayList();
i.add(new ArrayList());
((ArrayList)i.get(0)).add(0);
((ArrayList)i.get(0)).add(0,2);
((ArrayList)i.get(0)).remove(0);
i.add(new String("1"));
i.add(1,new int[] {2});i.add(2,2);i.set(2,1);
print(i);
}
static void print(ArrayList i) {
for(Object j:i) {
if(j==(Integer)1)i.remove(j);
else System.out.print(j);
}
}
}
A:[0][2]
B:[0][I@5ca881b5
C:[I@5ca881b5[2]
D:[0][I@5ca881b51
E:コンパイルエラーが生じる
F:実行時に例外がスローされる
正解を確認する
mainメソッドでのリストiの準備
まず、print メソッドが呼び出される直前までに、main メソッドで ArrayList の i がどのように変化するかを見ていきます。
ArrayList i = new ArrayList(); i は空のリスト [] です。
i.add(new ArrayList()); i に空の ArrayList が追加されます。 i の状態: [ [] ]
((ArrayList)i.get(0)).add(0); i の 0番目の要素(リスト)に 0 が追加されます。 i の状態: [ [0] ]
((ArrayList)i.get(0)).add(0, 2); i の 0番目の要素(リスト)の 0番目に 2 が挿入されます。 i の状態: [ [2, 0] ]
((ArrayList)i.get(0)).remove(0); i の 0番目の要素(リスト)のが削除されます。 i の状態: [ [0] ]
i.add(new String("1")); i に文字列の "1" が追加されます。 i の状態: [ [0], "1" ]
i.add(1, new int[] {2}); i の 1番目に int の配列 {2} が挿入されます。 i の状態: [ [0], int[] {2}, "1" ]
i.add(2, 2); i の 2番目に Integer の 2 が挿入されます。 i の状態: [ [0], int[] {2}, 2, "1" ]
i.set(2, 1); i の 2番目の要素(2)が Integer の 1 に置き換えられます。
print(i) が呼び出される時点での i の最終的な状態は、以下の4つの要素を持つリストです。 [ [0], int[] {2}, 1, "1" ] (0番目: リスト、1番目: 配列、2番目: 整数1、3番目: 文字列"1")
printメソッドでのループ処理
次に、print メソッドがこのリスト i を処理します。for(Object j : i) というループは、リスト i の要素を 0番目から順番に j という変数に入れて処理していきます。
ループ 1回目
j には i の 0番目の要素 [0](リスト)が入ります。if (j == (Integer)1) の条件は false(偽)です。
else 側が実行され、System.out.print(j) によって [0] が出力されます。
ループ 2回目 j には i の 1番目の要素 int[] {2}(配列)が入ります。if の条件は false です。
else 側が実行され、System.out.print(j) によって配列の参照([I@ から始まる文字列)が出力されます。
ループ 3回目 j には i の 2番目の要素 1(Integer)が入ります。if (j == (Integer)1) の条件は true(真)です。
i.remove(j) が実行されます。これは i リストから (Integer)1 という値の要素を削除する命令です。i の 2番目の要素 1 が削除されます。この結果、リスト i 自体が変更され、[ [0], int[] {2}, "1" ] という状態になります。
ループ 4回目の試行 2番目の要素が削除されたため、繰り上がって3番目だった要素の"1"が現在評価中の要素となります。for ループは、次に処理する要素に進もうとします。"1"の次の要素はないためこれ以上処理する要素がなくループが終了します。したがって、"1" が処理されることはなく、プログラムは [0][I@... までを出力して終了します。
47:■■■に記述できるclass Aとして正しいものを2個選びなさい。
public class Main {
public static void main(String[] k) {
try(A a=new A()){}
}
}
■■■
A:class A implements Closeable{public void close(){}}
B:class A implements AutoCloseable{public void close(){}}
C:class A implements java.io.Closeable{
@Override
public boolean close() {}}
D:class A extends AutoCloseable{public void close(){}}
E:class A implements java.io.Closeable{
@Override
public void close(){}}
F:class A implements AutoCloseable{public void open(){}}
正解を確認する
try-with-resources文 (try(A a=new A()){}) がコンパイルエラーを起こさないようにclass Aを定義する必要があります。try-with-resourcesで使用できるクラスは、java.lang.AutoCloseableもしくはjava.io.Closeableを実装しなければなりません。与えられたコードではなにもimportされていないため、ioパッケージのCloseableを使用する場合はjava.io.Closeableと記述しなければいけません。AutoCloseableは暗黙的にすべてのクラスでimportされるjava.langパッケージに属するので単にAutoCloseableと記述できます。
またCloseableもしくはAutoCloseableを実装したクラスはpublic void close(){}をオーバーライドしなければなりません。
48:次のコードをコンパイル、実行したときの結果として正しいものを選びなさい。
public class Main {
private Integer i;
public static void main(String[] k) {
Main a=new Main();a.i=2;a.insert(1);
a.check();
}
void insert(int i) {
this.i=new Main().i;
}
void check() {
switch(this.i) {
case 0:System.out.println("zero");
break;
case 1:System.out.println("one");
break;
case 2:System.out.println("two");
break;
default:System.out.println("something else");
}
}
}
A:zero
B:one
C:two
D:something else
E:コンパイルエラー
F:実行時に例外がスローされる
正解を確認する
1. main メソッドの開始 Main a = new Main(); Main クラスの新しいインスタンスが作成され、変数 a に代入されます。このとき、インスタンス変数である Integer 型の i は、初期値として null が設定されます。 a.i = 2; 変数 a のインスタンス変数 i に 2 が代入されます。 a.insert(1); 次に、a の insert メソッドが呼び出されます。 2. insert メソッドの実行 insert メソッド(void insert(int i))が実行されます。引数 i には 1 が渡されます。メソッド内の処理(this.i = new Main().i;)が実行されます。new Main() によって、Main クラスの新しいインスタンスが一時的に作成されます。この新しいインスタンスのインスタンス変数 i は、初期値として null が設定されています。この null が、this.i(つまり、変数 a のインスタンス変数 i)に代入されます。結果として、a.i の値は null になります。 3. check メソッドの実行 a の a.check()が呼び出されます。check メソッド内の switch 文の条件式(switch(this.i))が実行されます。このとき、this.i の値は null です。 switch 文では、ラッパー型(Integerなど)を使う場合、null の値が渡されると、 NullPointerException が発生します。
49:次のコードはコンパイルエラーが生じる。C内に記述するとコンパイルエラーが出なくなるものはどれか。2個選べ。
interface A{
default void a() {}
}
interface B{
default void a() {}
}
public interface C extends A,B{}
A:default void b(){A.super.a();}
B:default void a(){throw new ArrayIndexOutOfBoundsException();}
C:default void a(){super.a();}
D:default void a(){A.super.a();}
E:default void b() throws Throwable{}
F:public static void a(){A.super.a();}
正解を確認する
このコードのコンパイルエラーは、インターフェース C が A と B の両方を継承した結果、void a() という同じシグネチャ(名前と引数)を持つデフォルトメソッドが二つ(A のものと B のもの)衝突しているために発生します。 コンパイラは、C の a() メソッドとしてどちらのデフォルト実装を使えばよいか判断できません。 このエラーを解決するには、インターフェース C 自身が void a() メソッドをオーバーライド(上書き)し、C としての a() の実装を明確に定義し直す必要があります。 選択肢B:この記述は正しいです。 これは、C インターフェースが a() メソッドをオーバーライドし、「例外をスローする」という新しい実装を定義しています。 C 独自の実装が提供されたため、A と B のどちらを採用するかという曖昧さがなくなり、コンパイルエラーは解消されます。 選択肢D:この記述は正しいです。 これは、C インターフェースが a() メソッドをオーバーライドし、その実装内容として「A のデフォルト実装(A.super.a())を明示的に呼び出す」と定義しています。 このように A.super.a() または B.super.a() のように、どちらの実装を呼び出すかを開発者が明示することで、曖昧さがなくなり、コンパイルエラーは解消されます。 その他の選択肢 A と E: default void b()... これは b() という新しいメソッドを定義しているだけで、衝突している a() メソッドの問題を解決していません。 C:親interfaceのディフォルトメソッドを実行するときは(親インターフェース名).super.(メソッド)のように記述しなければなりません。 F: public static void a()... static メソッドは、default メソッド(インスタンスメソッド)をオーバーライドすることはできません。a() の衝突は解決されません。また、staticメソッドでsuperキーワードを使用できません。
50:次のコードをコンパイル、実行したときの結果として正しいものを選びなさい。るものとする。
public class Main {
public static void main(String[] k) {
A.i="M";System.out.print(A.i); A a=new A();
B b=new B(6);
}
}
class A{
static String i;
static {System.out.print(0);}
{System.out.print(1);}
static {i="A";}
}
class B{
private static int i;
B(int i){
this();System.out.print(this.i);
}
{System.out.print(2);}
static {System.out.print(3);}
{i=4;}
B(){i=5;}
}
A:0M1325
B:M01235
C:0M126
D:M1025
E:コンパイルエラーが生じる
F:実行時に例外がスローされる
正解を確認する
A.i = "M"; A クラスに初めてアクセスします。 A クラスの static(静的)な要素が初期化されます。
static {System.out.print(0);} が実行されます。 出力: 0
static {i="A";} が実行され、i は "A" になります。 クラスの初期化が完了した後、A.i = "M"; が実行され、i は "M" に上書きされます。
System.out.print(A.i); A.i の現在の値である "M" が出力されます。 出力: M
A a = new A(); A のインスタンスを作成します。 インスタンス初期化ブロックが実行されます。
{System.out.print(1);} が実行されます。 出力: 1
B b = new B(6); B クラスに初めてアクセスします。 B クラスの static な要素が初期化されます。
static {System.out.print(3);} が実行されます。 出力: 3
次に B のインスタンスを作成するため、B(6) コンストラクタが呼び出されます。
B(int i) コンストラクタの this(); により、引数なしの B() コンストラクタが先に呼び出されます。
B() コンストラクタが実行される 前 に、インスタンス初期化ブロックが実行されます。
{System.out.print(2);} が実行されます。 出力: 2
{i=4;} が実行され、static な B.i は 4 になります。
次に B() コンストラクタの本体が実行されます。i=5; が実行され、static な B.i は 5 になります。
B() が終わり、B(int i) コンストラクタに戻ります。
System.out.print(this.i); が実行されます。
B クラスには i という名前のインスタンスフィールドは無く、static フィールド i しかないため、this.i は static な B.i を指します。B.i の現在の値である 5 が出力されます。
コメント