11:次のコードをコンパイル、実行したときの結果として正しいものを選びなさい。
package a;
public class A{
protected static boolean i;
A(boolean j){
if(!i)System.out.print("A");
this.i=j;
}
A(String k){
this(true);
if(!(k==null))System.out.print(k.toUpperCase());
}
}
package b;
import a.A;
public class Main{
public static void main(String[] args) {
A b=new A(A.i);//line A
A a=new A(null);//line B
A c=new A(new String("a"));//line C
}
}
A:line A~Cのいずれかでコンパイルエラーが生じる
B:line A~Cのいずれか2か所でコンパイルエラーが生じる
C:line A~Cのすべてでコンパイルエラーが生じる
D:AAA
E:AA
F:A
G:何も出力されない
正解を確認する
コンパイルエラーが生じるのは、パッケージプライベートなメンバーへのアクセス違反が原因です。
1. クラス A のコンストラクタのアクセス権
package a の中のクラス A のコンストラクタは、どちらもアクセス修飾子が省略されています。
A(boolean j){ ... }
A(String k){ ... }
アクセス修飾子が省略された場合、その修飾子はパッケージプライベート(デフォルトアクセス)となり、定義されたパッケージ内(package a)からしかアクセスできません。
2. Main クラスからのアクセス違反
Main クラスは package b に属しており、A クラスとは異なるパッケージにあります。
main メソッド内のすべてのコンストラクタ呼び出しは、異なるパッケージからパッケージプライベートなコンストラクタにアクセスしようとしているため、すべてコンパイルエラーとなります。
line A: A b = new A(A.i); → コンストラクタ A(boolean) へのアクセス違反。
line B: A a = new A(null); → コンストラクタ A(String) へのアクセス違反。
line C: A c = new A(new String("a")); → コンストラクタ A(String) へのアクセス違反。
したがって、line A から C のすべてでコンパイルエラーが発生します。
12:次のコードをコンパイル、実行したときの結果として正しいものを選びなさい。
package a;import b.A;
public class Main extends A{
int i=12;
Main(int i) {
super(i);
}
public int i(int i) {
return this.i+=i;
}
public static void main(String[] args) {
A a=new Main(3);
Main m=new Main(2);
a.i(a);a.i();a.i(a.i);m.i(m);m.i();m.i(m.i);
System.out.println(""+a.i+((Main)a).i+m.i+((A)m).i);
}
}
package b;
public class A{
public int i=2;
protected A(int i) {
this.i+=i*2;
}
prublic void i(A a) {
a.i/=this.i+1;
}
public void i() {
this.i+=i+5;
}
public int i(int i) {
return i+10;
}
}
A:512245
B:517245
C:5.112245.1
D:5.117245.1
E:1012202
F:コンパイルエラー
正解を確認する
1. 初期化
まず、2つのオブジェクトが初期化されます。
A a = new Main(3):
super(3) が実行され、a のスーパークラス側 (A.i) は 2 + (3 * 2) = 8 に設定されます。
サブクラス側 (Main.i) は初期値 12 のままです。
Main m = new Main(2):
super(2) が実行され、m のスーパークラス側 (A.i) は 2 + (2 * 2) = 6 に設定されます。
サブクラス側 (Main.i) は初期値 12 のままです。
初期状態: a.A.i=8, a.Main.i=12 / m.A.i=6, m.Main.i=12
2. メソッド呼び出しとフィールドの更新
処理 1〜2: a.i(a) と a.i()
a.i(a) が実行される際、静的型Aのメソッド A.i(A a) が実行されます。このメソッドは、a.A.i フィールドを参照し、8 / 9 = 0 を計算し、a.A.i を 5 にします。(8 / (8 + 1) = 0 の後、次の a.i() で 0 + 0 + 5 = 5 になる)。
この時点で、a.A.i は 5 に更新されますが、a.Main.i は 12 のままです。
処理 3: a.i(a.i) の重要性
呼び出しは a に対して行われ、シグネチャは i(int) です。A クラスの i(int) は Main クラスでオーバーライドされているため、オブジェクトの実体である Main.i(int i) が実行されます。
引数 a.i は、参照変数 a の静的型がAであるため、隠蔽されたスーパークラスフィールド a.A.i の値 5 を参照します。
実行されるコードは Main.i(int i) の中の this.i += i; です。this.i は常にサブクラスのフィールド Main.i を参照します。
更新: a.Main.i の値 12 に、引数の値 5 が加算され、a.Main.i は 17 に更新されます。
処理 4〜5: m.i(m) と m.i()
a と同様の処理が m に対して行われます。m.A.i が 6 から 0 になり、最終的に 5 に更新されます。
処理 6: m.i(m.i)
a と同様に Main.i(int i) が実行されます。
引数 m.i は、参照変数 m の静的型がMainであるため、m.Main.i の値 12 を参照します。
更新: m.Main.i の値 12 に、引数の値 12 が加算され、m.Main.i は 24 に更新されます。
3. 最終的な出力
System.out.println(""+a.i+((Main)a).i+m.i+((A)m).i);
a.i: 参照型 A → a.A.i の値 5
((Main)a).i: 参照型 Main → a.Main.i の値 17
m.i: 参照型 Main → m.Main.i の値 24
((A)m).i: 参照型 A → m.A.i の値 5
これらを連結し、517245 が最終的な出力となります。
13:class Aに記述できるメソッドは次のうちどれか。
public class Main {
public static void main(String[] args) {
}
final void a() {}
protected void b() {}
private void c() {}
}
class A extends Main{
}
A:public void a(){}
B:void b(){}
C:void c(){}
D:@Override
public void c(){}
E:CとD
F:B、CとD
正解を確認する
A: public void a(){} → コンパイルエラー
スーパークラスのメソッド a() には final 修飾子が付いています。final メソッドは子クラスで再定義(オーバーライド)することが禁止されているため、エラーとなります。
B: void b(){} → コンパイルエラー
スーパークラスのメソッド b() は protected です。オーバーライドするメソッドのアクセス修飾子は、スーパークラスよりもアクセスレベルを弱くすることはできません。
選択肢 B の void b(){} はパッケージプライベート(デフォルト)アクセスであり、protected よりもアクセスレベルが弱くなっているため、オーバーライドのルールに違反し、エラーとなります。
C: void c(){} → コンパイルエラーなし
スーパークラスのメソッド c() は private です。private メンバーは子クラスに継承されません。
したがって、A クラス内で void c(){} を定義することは、オーバーライドではなく、A クラス独自の新しいメソッドを定義しているに過ぎません。これは合法です。
D: @Override public void c(){} → コンパイルエラー
スーパークラスの c() メソッドは継承されていないため、オーバーライドすべきメソッドが存在しません。存在しないメソッドに @Override アノテーションを付けると、エラーとなります。
厳密なJavaのルールに基づき、コンパイルエラーが生じない定義は C のみです。
14:次のコードをコンパイル、実行したときの結果として正しいものを選びなさい。
public class Main {
public static void main(String[] args) {
Main a=new A("1");A b=new A(1);Main c=new Main(2);
}
private void a() {System.out.print("a");}
void b() {System.out.print("b"); }
Main(){a();b();}
Main(int i){this(); }
}
class A extends Main{
void a() {System.out.print("A");}
void b() {System.out.print("B");}
A(int i){super(i);}
A(String i){System.out.print("S");}
}
A:Sabab
B:ABSABab
C:SABab
D:aBSaBab
E:コンパイルエラー
F:実行時に例外がスローされる
正解を確認する
この問題を解く鍵は、コンストラクタの呼び出し順序と、メソッドのオーバーライド(特に private メソッドの挙動)を理解することです。
private メソッドはオーバーライドされない:
Main クラスの a() メソッドは private です。これは、Main クラスの外部から隠されており、サブクラスである A で a() を定義しても、それはオーバーライドではなく、全く別の新しいメソッドの定義となります。
したがって、Main クラスのコンストラクta内で a() が呼ばれた場合、それは必ず Main クラスの a() メソッドを指します。
Main クラスの b() メソッドはアクセス修飾子がないため同じパッケージ内のサブクラスでオーバーライドできます。
コンストラクタ内で b() が呼ばれた場合、実際に生成されているオブジェクトのクラス(インスタンスの型)に応じて、Main の b() か A の b() のどちらかが実行されます(ポリモーフィズム)。
ステップごとの実行トレース
1. Main a = new A("1");
A クラスの A(String i) コンストラクタが呼ばれます。
このコンストラクタには super() の呼び出しが明記されていないため、暗黙的にスーパークラス (Main) の引数なしコンストラクタ super() が最初に呼ばれます。
Main() コンストラクタが実行されます。
a() が呼ばれます。これは private なので Main クラスの a() が実行され、"a" が出力されます。
b() が呼ばれます。このとき生成されているオブジェクトは A なので、オーバーライドされた A クラスの b() が実行され、"B" が出力されます。
Main() の実行が終わり、A(String i) コンストラクタに戻ります。
System.out.print("S"); が実行され、"S" が出力されます。
ここまでの出力: aBS
2. A b = new A(1);
A クラスの A(int i) コンストラクタが呼ばれます。
super(i) により、スーパークラス (Main) の Main(int i) コンストラクタが呼ばれます。
Main(int i) コンストラクタ内の this() により、同じクラスの引数なしコンストラクタ Main() が呼ばれます。
Main() コンストラクタが実行されます。
a() が呼ばれます。Main の private メソッドなので "a" が出力されます。
b() が呼ばれます。生成されているオブジェクトは A なので、オーバーライドされた A の b() が実行され、"B" が出力されます。
Main() の実行が終わり、Main(int i) に戻り、それも終了し、A(int i) に戻って終了します。
ここまでの出力: aBSaB
3. Main c = new Main(2);
Main クラスの Main(int i) コンストラクタが呼ばれます。
this() により、同じクラスの引数なしコンストラクタ Main() が呼ばれます。
Main() コンストラクタが実行されます。
a() が呼ばれます。Main の private メソッドなので "a" が出力されます。
b() が呼ばれます。このとき生成されているオブジェクトは Main なので、Main クラスの b() が実行され、"b" が出力されます。
Main() が終了し、Main(int i) も終了します。
以上の流れから、最終的な出力は aBSaBab となります。
15:次のコードは何か所でコンパイルエラーが生じるか。
public class $ {
private var _=2;
public static void main(String[] args) {}
public static var a%(var i) {
var j= {1,2,3};
var k=new Integer[2][];
var _k\1$=new Short[] {3,4};
var 2k=new Byte[] {5};
var m=null;
int sum=0;
for(var l:j) {
sum+=(int)l;
}
}
}
A:4
B:5
C:6
D:7
E:8
F:9
正解を確認する
このコードには、var の使用制限、識別子の命名規則、およびメソッド名の命名規則に関する違反が複合的に含まれています。
1. メソッド名のエラー(1箇所)
public static var a%(var i) (メソッド名)
エラー1: メソッド名 a% に使用されているパーセント記号(%)は、識別子(メソッド名、変数名など)に使用できない文字です。識別子に使える記号は_と$のみです。
2. var の使用制限に関するエラー(5箇所)
var は、ローカル変数にのみ使用でき、初期化式から型が明確に推論できる必要があります。
private var i=2;
エラー2: var はクラスのフィールド(インスタンス変数)の宣言には使用できません。
public static var a%(var i) (戻り値の型)
エラー3: var はメソッドの戻り値の型として使用できません。
public static var a%(var i) (引数 i の型)
エラー4: var はメソッドの引数(パラメータ)の型として使用できません。
var j= {1,2,3};
エラー5: 配列初期化子({...})だけでは、コンパイラが型を明確に推論できないため、var は使用できません(new int[]{...} のようにする必要がある)。
var m=null;
エラー6: var は初期化式から非nullの型を推論できなければなりません。null だけでは型が確定しないため、使用できません。
3. 変数名の命名規則に関するエラー(2箇所)
var _k\1$=new Short[] {3,4};
エラー7: 変数名(識別子)にバックスラッシュ(\)は使用できません。識別子に使える記号は_と$のみです。
var 2k=new Byte[] {5};
エラー8: 変数名(識別子)は、数字で始めることができません。
したがって、コンパイルエラーの総数は 8 です。
| オラクル認定資格教科書 Javaプログラマ Silver SE 17(試験番号1Z0-825) (EXAMPRESS) [ 根本 有子 ] 価格:4,620円(税込、送料無料) (2025/10/7時点) 楽天で購入 |
16:次のコード断片をコンパイルしたときline A, line B, line Cのどこでコンパイルエラーが生じるか。
public class Main {
public static void main(String[] args) {
String i[]= {" a \"b\n",new String("""
a "b
"""), """
a "b"""};
System.out.println(""+(i[0]==i[1])
+(i[0].equals(i[1]))
+(i[1]==i[2])
+(i[0]==i[1].intern()));
}
}
A:falsefalsefalsefalse
B:truetruefalsetrue
C:falsefalsefalsetrue
D:truetruetruetrue
E:falsetruefalsetrue
F:コンパイルエラー
G:実行時に例外がスローされる
正解を確認する
まず、配列 i の要素がどのような文字列インスタンスを持つかを確認します。
i[0]: " a \"b\n"
これは通常の文字列リテラルです。コンパイル時に文字列定数プール(String Pool)に格納されます。値は「 a "b」の後に改行文字(\n)が続くものです。
i[1]: new String(""" a "b""")
これはText Block("""...""")の内容を、明示的に new String() を使ってヒープ領域に新しいインスタンスとして生成しています。Text Blockのインデント処理後、値は i[0] と同じ「 a "b」の後に改行文字(\n)が続くものになります。
i[2]: """a "b"""
これもText Blockですが、リテラルとして扱われます。共通インデントの処理後、値は「a "b」の後に改行文字がないものになります。
比較処理
① i[0]==i[1]
i[0] は文字列プール内のインスタンスを参照しています。
i[1] は new String() でヒープに新しく作られたインスタンスを参照しています。
参照先のアドレスが異なるため、結果は false です。
② i[0].equals(i[1])
i[0] と i[1] が持つ文字列の内容は、どちらも同じです。
equals() は内容を比較するため、結果は true です。
③ i[1]==i[2]
i[1] の内容は改行\nありです。
i[2] の内容は改行なしです。
そもそも文字列の値が異なるため、参照先のアドレスも異なり、結果は false です。
④ i[0]==i[1].intern()
i[1].intern() は i[1] の内容に対応するインスタンスを文字列プールから取得します。
i[0] も同じ内容の文字列プール内のインスタンスを参照しています。
どちらも文字列プール内の同一のインスタンスを参照するため、結果は true です。
最終結果
4つのブーリアン値を文字列として連結すると以下のようになります。
(false)+(true)+(false)+(true)→"falsetruefalsetrue"
17:次のうちコンパイルエラーが生じないものを2個選びなさい。
A:float f=3._2___2_f;
B:int i=0_5_2;
C:int j=0b_1111;
D:int k=0xf_5_abcdE;
E:int l=08_777;
F:int m=0b2___10;
正解を確認する
A: エラーが生じる float f=3._2___2_f; エラー理由: アンダースコアは小数点(.)の直前または直後に置くことはできません。このコードでは 3._ の部分でルールに違反しています。 B: エラーが生じない int i=0_5_2; 解説: 10進数(ここでは10進数として扱われます)または8進数(0から始まる)として、数字の間にアンダースコアを挿入することは許可されています。このリテラルは8進数 052 と解釈され、10進数の 42 となります。 C: エラーが生じる int j=0b_1111; エラー理由: アンダースコアは、基数を示すプレフィックス(0b や 0x など)の直後に置くことはできません。このコードでは 0b_ の部分でルールに違反しています。 D: エラーが生じない int k=0xf_5_abcdE; 解説: 16進数リテラル(0xから始まる)において、数字の間にアンダースコアを挿入することは許可されています。また、16進数の E の直後にアンダースコアがないため、型サフィックス(LやFなど)の直前にアンダースコアを置くというルールにも違反していません。(この場合は型サフィックスがないため問題ありません)。このリテラルは16進数の 0xF5ABCDE と解釈されます。 E: エラーが生じる int l=08_777; エラー理由: 0 で始まる整数リテラルは8進数として扱われますが、8進数リテラルに数字の 8 や 9 を含めることはできません。このコードには 8 が含まれているため、コンパイルエラーになります。 F: エラーが生じる int m=0b2___10; エラー理由: 2進数リテラル(0bから始まる)には、数字の 0 と 1 しか含めることができません。このコードには 2 が含まれているため、コンパイルエラーになります。 補足:アンダースコア使用の禁止される位置 Javaで数値リテラルにアンダースコアを使用する際、禁止されている位置は以下の通りです。 リテラルの最初または最後 例: _100, 100_ 小数点(.)の直前または直後 例: 3_.14, 3._14 基数プレフィックス(0b, 0x など)の直後 例: 0b_1101, 0x_FF 型サフィックス(L, f, F など)の直前 例: 100_L, 3.14_f
18:package a 内にソースファイルA.javaがあり、このファイル内にclass Bがある。これらに関連したコマンドに関する次の記述のうち正しいものを個選べ。
A:>java a/A.java 2
>java a.B
上記のコマンドでclass Aおよびclass Bのメインメソッドを順に実行できる。
B:>javac A.java
>java B
上記のコマンドでclass Bのメインメソッドを実行できる。
C:>javac -d . a/A.java
>java -cp .. a.B
でclass Bのメインメソッドを実行できる。
D:>java a/A.java java \”a\”
でclass Aのメインメソッドを実行できる。
E:>javac a/A
>java a.A
でclass Aのメインメソッドを実行できる。
F:すべて正しくない
正解を確認する
D: 正しい Java 11以降では、java コマンドを使用して単一のソースファイル(.java)を直接実行できます(JEP 330)。この際、コンパイルはメモリ上で行われます。 java a/A.java は、A.java ファイル内の最初のトップレベルクラスclass Aの main メソッドを実行します。 java "a" は、main(String[] args) メソッドに渡されるコマンドライン引数です。引数として java と "a" の2つの文字列が渡されます。これは正しい実行形式です。 A: 誤り 1行目の java a/A.java 2 は、クラス A を実行します。 2行目の java a.B は、正しいクラス名の指定方法(完全修飾クラス名)ですが、単一ソースファイル実行モード(1行目)では、コンパイルされたクラスはインメモリに存在し、通常、後続の java コマンドでは見つけられません。これは、コンパイル後の .class ファイルが存在し、クラスパスが正しく設定されている場合に有効な実行方法です。 B: 誤り ソースファイルは package a 内にあるため、a/A.java にあります。javac A.java は、ファイルを見つけられないか、パッケージ構造を無視してコンパイルしてしまう可能性があります。 また、パッケージ化されたクラス(a.B)を実行するには、java B ではなく、java a.B のように完全修飾クラス名で指定する必要があります。 C: 誤り コンパイルコマンド javac -d . a/A.java は、a/A.class と a/B.class をカレントディレクトリの下にa/ディレクトリ構造で出力するため、コンパイル自体は正しいです。 しかし、実行コマンド java -cp .. a.B の -cp .. は、クラスパスとしてカレントディレクトリの親ディレクトリを指定しています。クラスファイルはカレントディレクトリ直下の a/ 内にあるため、クラスパスは通常 -cp .(カレントディレクトリ)とすべきです。そのため、クラスローダーは a.B を見つけられません。 E: 誤り コンパイルコマンド javac a/A は、ファイル名として .java 拡張子が抜けているため、コンパイルできません。 また、実行コマンド java a.A は、コンパイルが成功し、カレントディレクトリにクラスパスが設定されていれば実行可能ですが、1行目が誤っているため全体として誤りです。
19:ファイルMain.javaにはsealed class Main permits A, C{}および、class B、class C、interface E、interface Fが記述されている。このファイル内に記述できるものは次のうちどれか。2個選びなさい。
A:sealed class A permits C extends Main implements E, F{}
B:final class G extends Main implements F{}
C:class A extends Main {}
D:non-sealed class A extends Main implements E, F{}
E:public final class A extends Main{}
F:non-sealed class A extends E implements Main{}
G:non-sealed interface G extends E, F{}
H:sealed interface A extends Main{}
正解を確認する
ファイル Main.java には sealed class Main permits A{} が定義されており、Main を直接継承できるのはクラス A のみに制限されています。permits 句で許可されたクラス (A) は、以下のいずれかの修飾子を必ず持つ必要があります。final、sealed、non-sealed。
エラーが生じないもの
D: non-sealed class A extends Main implements E, F{}
A は Main の permits 句で許可されています。
non-sealed 修飾子は、sealed クラスを継承するクラスに必要な修飾子であり、ルールに完全に合致しています。
Main を extends し、E と F を implements する文法も正しいです。
G: non-sealed interface G extends E, F{}
これは sealed class Main とは継承関係がない、独立したトップレベルのインターフェースの定義です。
interface G extends E, F は、既存のインターフェースを継承する正しい構文です。
non-sealed 修飾子は、厳密には通常のインターフェースでは不要ですが、文法的なエラーにはなりません(Java 17以降の仕様で許可されています)。
エラーが生じるもの
A: sealed class A permits C extends Main implements E, F{}
extends句、implements句、permits句の順番で記述します。
B: final class G extends Main implements F{}
Main の permits 句に G が含まれていません。sealed クラスの継承制限に違反します。
C: class A extends Main{}
許可されたクラス A に、必須である final、sealed、non-sealed の修飾子がありません。
E: public final class A extends Main{}
ファイル Main.java 内に複数のトップレベルクラス(Main, A, B, C など)が定義されている場合、通常はファイル名と同じクラスにのみ public 修飾子を付けられます。
ソースファイル名が Main.java であるため、ファイル内のトップレベルクラスの中で public 修飾子を付けられるのは class Main のみです(sealed class Main が public でないとしても、ファイル名と一致する型が唯一 public になる権利を持ちます)。
F: non-sealed class A extends E implements Main{}
class は interface (E) を extends できません。また、class は class (Main) を implements できません。
H: sealed interface A extends Main{}
インターフェースはクラス (Main) を extends できません。また、sealed interface は permits 句を省略できません。
20:次のコードをコンパイル、実行したときの結果として正しいものを選びなさい。
public class Main extends A implements B{
int i;
public static void main(String[] args) {
int j=new A().a(10);int k=new B().b(20);
System.out.println(j+k+new Main().i);
}
int a(int i){
this.i=2;
return i*2;
}
public int b(int i) {
this.i=3;
return this.i*3;
}
}
abstract class A{
int i;
abstract int a(int i);
A(){System.out.print(1);
}
}
interface B {
int i=1;
int b(int i);
}
A:132
B:183
C:116
D:84
E:1
F:コンパイルエラー
G:実行時に例外がスローされる
正解を確認する
new A()やnew B()のように、abstractなclassおよびinterfaceのインスタンスを作成できません。
コメント
問12の解法について1点質問させてください。
クラスAとMainが別パッケージにあり、メソッドがprotectedで定義されていますが、この場合、参照型を親クラス(A a)にしていると、子クラス内からでも a.i() にアクセスできない(Not Visibleになる)というルールがあったかと思います。
もしこの問題が『コンパイルが通る前提での計算ロジック』を問う意図であれば理解できるのですが、厳密なJavaの仕様としてはコンパイルエラーになる可能性はないでしょうか?ご確認いただけると嬉しいです
その通りです。コンパイルエラーになります。Eclipseですべて挙動を確認したと思っていましたが、漏れていたようです。修正しました。ありがとうございました。