Java Silver Java の概要と簡単なJavaプログラムの作成 問題

ゆめさくが作った練習問題です。本試験の問題ではありません。

Java の概要と簡単なJavaプログラムの作成の問題を1⁠0問、小分野ごとにまとめました。選ぶと、その場で正誤と解説が出ます。

ログインなしで解けます。答えはこのブラウザの中だけに残り、どこにも送りません。

この分野の小分野

  • main メソッド、コンパイルと実行、パッケージ(10問)

Java の概要と簡単なJavaプログラムの作成の問題

10 問

選ぶと、すぐに正誤と解説が出ます。選んだ答えは変えられません。

  1. main メソッド、コンパイルと実行、パッケージ

    問 1クラス Main に次のメソッドを 1 つだけ書き、javac Main.java のあと java Main で起動します。main メソッドとして起動できる宣言はどれですか。

  2. 問 2次のコードを Main.java に保存し、javac Main.java と java Main を順に実行したときの結果として正しいものはどれですか。

    public class Main {
        public static void start(String[] args) {
            System.out.println("start");
        }
    }
  3. 問 3ファイル src/app/Main.java の先頭に package app; があり、main メソッドは ok と出力します。javac -d out src/app/Main.java でコンパイルしたあと、同じディレクトリでプログラムを起動するコマンドとして正しいものはどれですか。

  4. 問 4次のコードを Hello.java という名前で保存し、JDK 17 で javac を使わずに java Hello.java を実行したときの結果として正しいものはどれですか。

    class Helper {
        static String name() { return "helper"; }
    }
    
    public class Hello {
        public static void main(String[] args) {
            System.out.println("hello " + Helper.name());
        }
    }
  5. 問 5次のコードをコンパイルし、コメントに書いたコマンドで実行したときの出力として正しいものはどれですか。

    // 実行のコマンド
    // java Main red "green blue" yellow
    public class Main {
        public static void main(String[] args) {
            System.out.println(args.length + " " + args[1]);
        }
    }
  6. 問 6次のコードをコンパイルしたときの結果として正しいものはどれですか。

    // ゆめさくの練習用のクラス
    import java.util.List;                        // (A)
    package app;                                  // (B)
    
    public class Main {
        public static void main(String[] args) {
            List<String> names = List.of("yume"); // (C)
            System.out.println(names);
        }
    }
  7. 問 7次の 3 つのファイルをまとめてコンパイルし、java app.Main で実行したときの結果として正しいものはどれですか。

    // shop/Item.java
    package shop;
    
    public class Item {
        public static String who() { return "shop"; }
    }
    
    // stock/Item.java
    package stock;
    
    public class Item {
        public static String who() { return "stock"; }
    }
    
    // app/Main.java
    package app;
    
    import shop.*;              // (A)
    import stock.Item;
    
    public class Main {
        public static void main(String[] args) {
            System.out.println(Item.who());   // (B)
        }
    }
  8. 問 8次のコードをコンパイルしたときの結果として正しいものはどれですか。

    import java.util.Date;                // (A)
    import java.sql.Date;                 // (B)
    
    public class Main {
        public static void main(String[] args) {
            Object d = null;              // (C)
            System.out.println(d);
        }
    }
  9. 問 9次の 3 つのファイルをまとめてコンパイルしたときの結果として正しいものはどれですか。

    // com/yume/Base.java
    package com.yume;
    
    public class Base {
        public static String name() { return "base"; }
    }
    
    // com/yume/util/Tool.java
    package com.yume.util;
    
    public class Tool {
        public static String help() { return "help"; }
    }
    
    // Main.java
    import com.yume.*;
    
    public class Main {
        public static void main(String[] args) {
            System.out.print(Base.name());      // (A)
            System.out.print(Math.max(1, 2));   // (B)
            System.out.print(Tool.help());      // (C)
        }
    }
  10. 問 10次のコードをコンパイルして実行したときの結果として正しいものはどれですか。

    import static java.lang.Math.max;
    import static java.lang.Integer.parseInt;
    
    public class Main {
        public static void main(String[] args) {
            int a = parseInt("12");                          // (A)
            System.out.println(max(a, 7) + Math.min(a, 7));  // (B)
        }
    }

10 問中 0 問に答えました

解説の一覧

解いたあとに読み返せるよう、全問の解説を並べています。問いを開くと解説が出ます。

main メソッド、コンパイルと実行、パッケージ

問1クラス Main に次のメソッドを 1 つだけ書き、javac Main.java のあと java Main で起動します。main メソッドとして起動できる宣言はどれですか。

正解は「public static void main(String... argv)」です。java コマンドが呼ぶ main は、public と static が付き、戻り値が void で、String の配列を 1 つ受け取るメソッドでなければなりません。言語仕様は String[] args と並べて String... args (可変長引数) の形も認めています。可変長引数は中身が String の配列なので条件を満たし、引数の名前も argv のように自由です。public static int main(String[] args) はコンパイルできますが、戻り値が void でないので起動時にエラーになります。public static void main(String args) も引数が配列ではないので、コンパイルは通っても起動できません。public void static main(String[] args) は修飾子 static が戻り値の型 void の後ろにあり、コンパイルエラーになります。修飾子は戻り値の型より前に書きます。出典 https://docs.oracle.com/javase/specs/jls/se1⁠7/html/jls-⁠1⁠2.html#jls-⁠1⁠2.1.4

問2次のコードを Main.java に保存し、javac Main.java と java Main を順に実行したときの結果として正しいものはどれですか。
public class Main {
    public static void start(String[] args) {
        System.out.println("start");
    }
}

正解は「コンパイルは成功し、java Main で main メソッドが無いというエラーになる」です。main メソッドが無いことは、言語の規則としては誤りではありません。クラスは main を持たなくてもよいので、javac Main.java は成功して Main.class ができます。java Main を実行すると、java コマンドは指定されたクラスを読み込み、public static void main(String[] args) を探して呼ぼうとします。このクラスには start しか無いので、main メソッドが見つからないというエラーを表示して、終了コード 1 で止まります。start と出力されるという選択肢は誤りで、java コマンドは名前が main のメソッドしか呼びません。引数の形が同じでも名前が違えば使われません。コンパイルエラーになるという選択肢は、main の有無をコンパイラが調べると考えた誤りです。何も出力されずに正常に終わるという選択肢も誤りで、起動に失敗したときはエラーの表示と 0 以外の終了コードになります。出典 https://docs.oracle.com/en/java/javase/1⁠7/docs/specs/man/java.html

問3ファイル src/app/Main.java の先頭に package app; があり、main メソッドは ok と出力します。javac -d out src/app/Main.java でコンパイルしたあと、同じディレクトリでプログラムを起動するコマンドとして正しいものはどれですか。

正解は「java -cp out app.Main」です。javac の -d はクラスファイルを置く先のディレクトリを決めるオプションで、パッケージに属するクラスはパッケージの名に合わせたサブディレクトリに置かれます。そのため Main.class は out/app/Main.class にできます。java コマンドには、クラスパスの起点 (ここでは out) と、パッケージ名を含む完全な名前 app.Main を渡します。java はクラスパスの out から app/Main.class をたどって読み込みます。java -cp out Main はパッケージ名が欠けていて、out の直下に Main.class が無いので起動できません。java -cp out/app Main はファイルの場所には届いていますが、そのクラスの本当の名前は app.Main なので、名前が合わずに読み込めません。java -cp src app.Main はソースのあるディレクトリを指しており、そこにはクラスファイルが無いので見つかりません。出典 https://docs.oracle.com/en/java/javase/1⁠7/docs/specs/man/java.html

問4次のコードを Hello.java という名前で保存し、JDK 1⁠7 で javac を使わずに java Hello.java を実行したときの結果として正しいものはどれですか。
class Helper {
    static String name() { return "helper"; }
}

public class Hello {
    public static void main(String[] args) {
        System.out.println("hello " + Helper.name());
    }
}

正解は「最初のクラス Helper に main メソッドが無いのでエラーになる」です。java コマンドに .java で終わるファイルを渡すと、ソースファイル・モードで動きます。ファイルはメモリの中でコンパイルされ、ファイルの中で最初に出てくる最上位のクラスが実行されます。このモードでは public が付いているかどうかやファイル名とクラス名の一致は関係なく、上から最初のクラスが選ばれます (JDK 1⁠7 の決まり。試験の版も 1⁠7)。ここで最初のクラスは Helper で、main メソッドを持たないので、main が見つからないというエラーで止まります。hello helper と出力されるという選択肢は、public のクラスやファイル名と同じ名前のクラスが選ばれると考えた誤りです。Hello.class が作られるという選択肢も誤りで、ソースファイル・モードではクラスファイルを書き出しません。1 つのファイルに複数の最上位クラスを書くこと自体は許されているので、コンパイルエラーにもなりません。出典 https://docs.oracle.com/en/java/javase/1⁠7/docs/specs/man/java.html#using-⁠source-⁠file-⁠mode-⁠to-⁠launch-⁠single-⁠file-⁠source-⁠code-⁠programs

問5次のコードをコンパイルし、コメントに書いたコマンドで実行したときの出力として正しいものはどれですか。
// 実行のコマンド
// java Main red "green blue" yellow
public class Main {
    public static void main(String[] args) {
        System.out.println(args.length + " " + args[1]);
    }
}

正解は「3 green blue」です。java コマンドでは、クラス名より後ろに書いた語が main の引数 args に順に入ります。クラス名 Main 自身は args に入らないので、args[0] は red です。語の区切りは空白ですが、ダブルクォートで囲んだ green blue はシェルが 1 つの引数としてまとめて渡します。そのため args は red、green blue、yellow の 3 つになり、args.length は 3、args[1] は green blue です。出力は 3 green blue です。4 red はクラス名も args[0] に入ると考えた誤りです。4 green はダブルクォートで囲んでも空白で分かれると考えた誤りです。3 green は数は合っていますが、囲んだ中の空白で値が切れると考えた誤りです。出典 https://docs.oracle.com/en/java/javase/1⁠7/docs/specs/man/java.html

問6次のコードをコンパイルしたときの結果として正しいものはどれですか。
// ゆめさくの練習用のクラス
import java.util.List;                        // (A)
package app;                                  // (B)

public class Main {
    public static void main(String[] args) {
        List<String> names = List.of("yume"); // (C)
        System.out.println(names);
    }
}

正解は「(B) の行でコンパイルエラーになる」です。1 つのソースファイルの並びは、package 宣言、import 宣言、クラスなどの宣言の順と決まっています。package 宣言は書かなくてもよいのですが、書くなら 1 つだけで、ファイルの先頭に置きます。ただしコメントや空行は宣言ではないので、package より前にあってもかまいません。このコードでは import の後ろに package app; があるので、(B) の行でコンパイルエラーになります。(A) の import は、package 宣言の無いファイルの先頭としては正しい書き方なので、ここでは誤りになりません。(C) の List.of は Java 9 から使えるメソッドで、java.util.List を import しているので問題ありません。コンパイルに成功するという選択肢は、宣言の順番を気にしなくてよいと考えた誤りです。出典 https://docs.oracle.com/javase/specs/jls/se1⁠7/html/jls-⁠7.html#jls-⁠7.3

問7次の 3 つのファイルをまとめてコンパイルし、java app.Main で実行したときの結果として正しいものはどれですか。
// shop/Item.java
package shop;

public class Item {
    public static String who() { return "shop"; }
}

// stock/Item.java
package stock;

public class Item {
    public static String who() { return "stock"; }
}

// app/Main.java
package app;

import shop.*;              // (A)
import stock.Item;

public class Main {
    public static void main(String[] args) {
        System.out.println(Item.who());   // (B)
    }
}

正解は「stock と出力される」です。import shop.*; は型オンデマンドの import で、shop パッケージのクラスを、名前が必要になったときに使えるようにします。一方 import stock.Item; は単一型の import で、Item という名前を stock.Item に結び付けます。言語仕様では、オンデマンドの import で入る名前は、単一型の import で入った同じ名前に隠されます。そのため Item は stock.Item を指し、stock と出力されます。shop と出力されるという選択肢は、先に書いた import が優先されると考えた誤りです。順番ではなく import の種類で決まります。(B) で Item があいまいになってコンパイルエラーになるのは、オンデマンドの import 2 つが同じ名前を持ち込み、その名前を使ったときです。単一型の import があればあいまいになりません。(A) の import shop.*; の行そのものも正しい書き方なので、エラーにはなりません。出典 https://docs.oracle.com/javase/specs/jls/se1⁠7/html/jls-⁠7.html#jls-⁠7.5.2

問8次のコードをコンパイルしたときの結果として正しいものはどれですか。
import java.util.Date;                // (A)
import java.sql.Date;                 // (B)

public class Main {
    public static void main(String[] args) {
        Object d = null;              // (C)
        System.out.println(d);
    }
}

正解は「(B) の行でコンパイルエラーになる」です。単一型の import を 2 つ書き、そのクラスの単純名 (パッケージを除いた名前) が同じだと、コンパイルエラーになります。java.util.Date と java.sql.Date はどちらも単純名が Date なので、2 つ目の (B) の import の行で、Date はもう import されているというエラーになります。このエラーは Date という名前をコードで使うかどうかに関係なく、import の行そのもので起きます。(A) の import は 1 つ目なので正しく、ここではエラーになりません。(C) の行は Date を使わず Object 型の変数を宣言しているだけなので、import の衝突とは関係なく通ります。名前があいまいだというエラーが使った行で出るのは、オンデマンドの import (java.util.* と java.sql.*) を 2 つ書いた場合です。両方のクラスを使いたいときは、片方を import せず java.sql.Date のように完全な名前で書きます。出典 https://docs.oracle.com/javase/specs/jls/se1⁠7/html/jls-⁠7.html#jls-⁠7.5.1

問9次の 3 つのファイルをまとめてコンパイルしたときの結果として正しいものはどれですか。
// com/yume/Base.java
package com.yume;

public class Base {
    public static String name() { return "base"; }
}

// com/yume/util/Tool.java
package com.yume.util;

public class Tool {
    public static String help() { return "help"; }
}

// Main.java
import com.yume.*;

public class Main {
    public static void main(String[] args) {
        System.out.print(Base.name());      // (A)
        System.out.print(Math.max(1, 2));   // (B)
        System.out.print(Tool.help());      // (C)
    }
}

正解は「(C) の行でコンパイルエラーになる」です。import com.yume.*; で使えるようになるのは、com.yume パッケージに直接属するクラスだけです。com.yume.util は名前が似ていても別のパッケージで、* はサブパッケージの中までは入りません。そのため Tool は見つからず、(C) の行でシンボルが見つからないというコンパイルエラーになります。使うには import com.yume.util.*; か import com.yume.util.Tool; を足します。(A) の Base は com.yume に属するので、import com.yume.*; で使えます。(B) の Math は java.lang パッケージのクラスで、java.lang はすべてのファイルに暗黙に import されているので、import 文が無くても使えます。コンパイルに成功するという選択肢は、* で下の階層のパッケージまで入ると考えた誤りです。出典 https://docs.oracle.com/javase/specs/jls/se1⁠7/html/jls-⁠7.html#jls-⁠7.5.2

問10次のコードをコンパイルして実行したときの結果として正しいものはどれですか。
import static java.lang.Math.max;
import static java.lang.Integer.parseInt;

public class Main {
    public static void main(String[] args) {
        int a = parseInt("12");                          // (A)
        System.out.println(max(a, 7) + Math.min(a, 7));  // (B)
    }
}

正解は「1⁠9 と出力される」です。import static はクラスの static なメンバを、クラス名を付けずに使えるようにする宣言です。書き方は import static の順で、static import の順ではありません。import static java.lang.Math.max; で max を、import static java.lang.Integer.parseInt; で parseInt を、名前だけで呼べます。(A) で a は 1⁠2 になり、(B) の max(a, 7) は 1⁠2、Math.min(a, 7) は 7 です。どちらも int なので足し算になり、1⁠9 と出力されます。1⁠2⁠7 は文字列の連結と考えた誤りで、+ の両側が int なら数の足し算です。(A) でエラーになるという選択肢は、parseInt を static import で呼べないと考えた誤りです。(B) でエラーになるという選択肢は、min を static import していないと Math.min も使えないと考えた誤りです。Math は java.lang のクラスなので、クラス名を付ければいつでも呼べます。出典 https://docs.oracle.com/javase/specs/jls/se1⁠7/html/jls-⁠7.html#jls-⁠7.5.3

ほかの分野

Java Silverの頁に、6分野の入口と試験の案内があります。

続きはゆめさくで

試験の知識を仕事につなげる一歩を、ここにまとめています。