Skip to content

APG4b Java版 第1章: 基本文法

1.00. はじめに

Java とは

Java はコンパイル言語であり、C++ と並んで競技プログラミングで広く使われています。

Java のメリット:

  • コンパイル言語のため実行速度が速い (Python の数十倍)
  • 型安全 (コンパイル時にエラーを検出できる)
  • int 型は 32bit、long 型は 64bit と明確な範囲をもつ
  • 標準ライブラリが充実している

Java のデメリット:

  • 静的型付けのため、コードが冗長になりやすい
  • Python のような多倍長整数が標準では使えない (BigInteger クラスを使う必要がある)
  • コンパイルが必要なため、実行までの手順が多い

AtCoder での Java 環境

AtCoder では Java (OpenJDK 21) を選択して提出します。

Hello, world!

Java で最初に書くプログラムは次のようになります。

java
public class Main {
    public static void main(String[] args) {
        System.out.println("Hello, world!");
    }
}

実行結果:

Hello, world!

Java のプログラムは必ず public class Mainpublic static void main(String[] args) から始まります。この部分は「おまじない」として毎回書く必要があります。実際に処理を書く部分は main メソッドの {} の間です。

この教材全体を通して、コードは基本的にこの形式で書きます。省略している場合でも、実際には public class Main { public static void main(String[] args) { ... } } の中に書くことを忘れないでください。


1.01. 出力とコメント

キーポイント

  • 文字列や数値の出力には System.out.println() を使う
  • 改行なし出力は System.out.print()
  • 1行コメントは //、複数行コメントは /* */

文字列の出力

System.out.println() は括弧の中の内容を出力し、最後に改行を挿入します。文字列 (テキスト) を出力するときは " (ダブルクォート) で囲みます。

java
public class Main {
    public static void main(String[] args) {
        System.out.println("Hello, world!");
    }
}

実行結果:

Hello, world!

別の文字列を出力したい場合も同様です。

java
System.out.println("Javaだいすき");

実行結果:

Javaだいすき

数値の出力

文字列だけでなく、数値をそのまま渡すこともできます。

java
System.out.println(123);

実行結果:

123

数値は " で囲まなくてよいことに注意してください。

複数の出力 (改行区切り)

System.out.println() を複数回呼び出すと、それぞれ改行されて出力されます。

java
System.out.println("Hello, world!");
System.out.println(123);

実行結果:

Hello, world!
123

1行目に "Hello, world!"、2行目に 123 が出力されます。

改行なし出力

System.out.print() は末尾に改行を挿入しません。

java
System.out.print("Hello, world! ");
System.out.println(123);

実行結果:

Hello, world! 123

1つ目の print() は改行なしで "Hello, world! " を出力し、2つ目の println()123 を出力してから改行します。結果として同じ行に並んで表示されます。

スペース区切りで複数値を出力

+ 演算子で文字列を連結して出力することができます。

java
System.out.println("Hello, world! " + 123);

実行結果:

Hello, world! 123

変数を使って複数の値をスペース区切りで出力する例:

java
int a = 10, b = 20;
System.out.println(a + " " + b);

実行結果:

10 20

printf による書式付き出力

System.out.printf() を使うと書式を指定して出力できます。%d は整数、%n は改行を意味します。

java
System.out.printf("%d %d%n", 10, 20);

実行結果:

10 20

書式付き出力の詳細は第3章で説明します。

コメント

プログラム中にメモや説明を書きたいときは「コメント」を使います。コメントはプログラムの実行には影響しません。

1行コメント (//):

// から行末までがコメントになります。

java
// 123
// 456
// と出力するプログラムです
System.out.println(123);
System.out.println(456);

実行結果:

123
456

// 以降の部分はコメントなので、実行されるのは System.out.println(123)System.out.println(456) の2行だけです。

複数行コメント (/* */):

/* から */ までが複数行のコメントになります。

java
/*
 * System.out.println() は受け取った要素を出力する
 * 最後に改行が自動で挿入される
 */
System.out.println("こんにちは");

コメントアウト

一時的にコードを実行しないようにするために、コードをコメントにすることを「コメントアウト」といいます。

java
// System.out.println(123);
System.out.println(456);

実行結果:

456

1行目はコメントアウトされているので実行されず、456 だけが出力されます。

注意事項

  • 全角文字 (日本語など) はコメントや文字列の中だけ使用する。変数名や演算子には使えない
  • 文末には必ず ; (セミコロン) をつける。忘れるとコンパイルエラーになる

練習問題

EX1. コードテストと出力の練習


1.02. プログラムの書き方とエラー

キーポイント

  • Java はコンパイル言語: ソースコード → コンパイル → 実行の順で動作する
  • エラーには「コンパイルエラー」と「実行時エラー」がある
  • エラーメッセージをよく読んで原因を特定する

Java の基本構造

Java のプログラムは必ず以下の形式から始まります。

java
public class Main {
    public static void main(String[] args) {
        // ここに処理を書く
    }
}
  • public class Main : プログラムのクラス名を定義します。AtCoder では常に Main という名前を使います
  • public static void main(String[] args) : プログラムの実行開始地点 (エントリーポイント) です
  • {} で囲まれた部分がそれぞれのブロックです

AtCoder では常にこの形式でプログラムを書きます。慣れてくれば自然に書けるようになります。

エラーの種類

プログラムを書いていると必ずエラーが発生します。エラーには主に2種類あります。

コンパイルエラー (Compile Error):

文法が間違っているときに発生します。実行する前にコンパイルの段階で検出されます。エラーメッセージには行番号と原因が表示されます。

java
// セミコロンを忘れた例
System.out.println("Hello")  // ← ; がない → エラー

このような場合、error: ';' expected (「;」が期待されます) というメッセージが表示されます。

実行時エラー (Runtime Error):

文法は正しいが、実行中に問題が発生するエラーです。例えば、存在しない配列の要素にアクセスしようとした場合などです。

java
int[] a = {1, 2, 3};
System.out.println(a[5]);  // ArrayIndexOutOfBoundsException (インデックスが範囲外)

この例では配列 a の長さは3ですが、インデックス5番の要素にアクセスしようとしているため、実行時エラーが発生します。

論理エラー:

文法は正しく実行もできるが、意図した動作と異なる結果になるエラーです。コンパイラでは検出できないため、自分でテストして見つける必要があります。

エラーの対処法

  1. エラーメッセージの行番号を確認する
  2. その行とその周辺のコードを確認する
  3. 多くの場合、セミコロン忘れ、括弧の対応ミス、タイプミスが原因

練習問題

EX2. プログラムの書き方の練習


1.03. 四則演算と優先順位

キーポイント

  • Java の / は整数同士なら整数除算 (小数点以下切り捨て)
  • Python の // は存在しない
  • % の挙動が Python と異なる (負の数の場合)
  • べき乗は Math.pow() を使う

演算子一覧

演算子意味
+加算7 + 2 = 9
-減算7 - 2 = 5
*乗算7 * 2 = 14
/除算 (整数同士なら整数除算)7 / 2 = 3
%剰余7 % 2 = 1
Math.pow(a, b)べき乗Math.pow(7, 2) = 49.0

加算・減算・乗算

Python とほぼ同じように書けます。

java
public class Main {
    public static void main(String[] args) {
        System.out.println(7 + 2);  // 9
        System.out.println(7 - 2);  // 5
        System.out.println(7 * 2);  // 14
    }
}

実行結果:

9
5
14

除算

Java の /整数同士の場合、小数点以下を切り捨てます。これは Python の // (切り捨て除算) に対応しますが、負の数の場合に挙動が異なる点に注意が必要です。

java
System.out.println(7 / 2);    // 3  (整数除算: 小数点以下を切り捨て)
System.out.println(7.0 / 2);  // 3.5 (どちらかが小数なら浮動小数点除算)
System.out.println(-7 / 2);   // -3  (0方向への切り捨て ← Pythonとは異なる!)

Pythonとの違い:

  • Python の // は「負の無限大方向への切り捨て」: -7 // 2 = -4
  • Java の / は「0方向への切り捨て」: -7 / 2 = -3

べき乗

Java にはべき乗演算子 (**) がないため、Math.pow() を使います。戻り値は double (浮動小数点数) であることに注意してください。

java
System.out.println(Math.pow(7, 2));      // 49.0
System.out.println((int)Math.pow(7, 2)); // 49 (int に変換)

整数のべき乗を求める場合は、for ループで掛け算を繰り返す方法もあります:

java
long power = 1;
for (int i = 0; i < 2; i++) power *= 7;
System.out.println(power);  // 49

剰余

% 演算子は割り算の余りを求めます。

java
System.out.println(7 % 2);   // 1
System.out.println(-11 % 5); // -1 (Pythonでは 4 ← 符号が異なる!)

Pythonとの違い:

  • Python の % は常に非負の値を返す: -11 % 5 = 4
  • Java の % は被除数 (割られる数) の符号に依存する: -11 % 5 = -1

負の数で Python と同じ結果を得たい場合は Math.floorMod() を使います:

java
System.out.println(Math.floorMod(-11, 5));  // 4 (Pythonの % と同じ)
// または
int result = (((-11) % 5) + 5) % 5;  // 4

演算子の優先順位

算数と同じく、*/%+- より先に計算されます。

優先度演算子
*, /, %
+, -
java
System.out.println(3 + 4 * 5);    // 23  (4*5=20 を先に計算)
System.out.println(4 * (1 + 2));  // 12  (括弧の中を先に計算)
System.out.println(3 * 5 / 2);    // 7   (左から順に: 15/2=7)

ゼロ除算に注意

0で割ると実行時エラーが発生します。

java
System.out.println(3 / 0);   // ArithmeticException (実行時エラー)
System.out.println(3 % 0);   // ArithmeticException (実行時エラー)
System.out.println(3.0 / 0); // Infinity (浮動小数点では例外が発生しない)

練習問題

EX3. 計算問題


1.04. 変数と型

キーポイント

  • Java は静的型付け言語。変数を宣言するときに型を指定する
  • 主な型: int (32bit整数)、long (64bit整数)、double (浮動小数点)、String (文字列)、boolean (真偽値)
  • 大きな整数には long を使う (int は約21億まで)
  • 複合代入演算子 (+=, -= など) が使える

変数とは

変数とは、値を格納する「箱」のようなものです。変数を使うことで、値に名前をつけて管理できます。

Python では型を指定せずに変数を作れましたが、Java では変数を宣言するときに型を指定する必要があります

主な型

意味範囲
int32bit 整数約 -21億 〜 +21億
long64bit 整数約 -922京 〜 +922京
double64bit 浮動小数点有効桁数 約15桁
String文字列制限なし
boolean真偽値true / false
char1文字Unicode 文字

変数の宣言と代入

変数を使うには「型 変数名 = 値;」という形で宣言します。

java
int name = 10;
System.out.println(name);      // 10
System.out.println(name + 2);  // 12
System.out.println(name * 2);  // 20

実行結果:

10
12
20

name という変数に 10 を代入し、その後で name を使って計算しています。name + 210 + 2 = 12 と評価されます。

複数の変数を宣言する例:

java
int x = 3;
long y = -7300000000L;   // long リテラルは末尾に L をつける
double z = -7.3;
String s = "ABC";
boolean flag = true;

long 型の定数には末尾に L を付けます。付けないと int として扱われ、int の範囲を超えるとコンパイルエラーになります。

変数の上書き

= を使って変数の値を変更できます。

java
int x = 3;
System.out.println(x);  // 3
x = 10;
System.out.println(x);  // 10

実行結果:

3
10

最初に x = 3 と宣言し、その後 x = 10 で値を上書きしています。

式の代入

変数の値を別の変数に代入したり、計算式を代入することもできます。

java
int x = 3;
int y = x;          // y は x の値 (3) が代入される
int z = x * 10 + 2; // z は 3 * 10 + 2 = 32 が代入される
System.out.println(y);  // 3
System.out.println(z);  // 32

重要: Java の = は「等しい」ではなく「右辺の値を左辺に代入する」という意味です。x = 10 は「x と 10 が等しい」ではなく「x に 10 を代入する」という意味です。

int と long の使い分け

int 型は約21億 (2^31 - 1 = 2,147,483,647) までの値しか格納できません。競技プログラミングではこの上限を超えることが多いため、注意が必要です。

java
int a = 2000000000;
int b = 2000000000;
System.out.println(a + b);  // -294967296 (オーバーフロー!)

long la = 2000000000L;
long lb = 2000000000L;
System.out.println(la + lb);  // 4000000000 (正しい)

int + int の計算結果が int の範囲を超えると「オーバーフロー」が発生し、意図しない値になります。迷ったら long を使うのが安全です。

double の精度

double は浮動小数点数を扱いますが、すべての実数を正確に表現することはできません。

java
System.out.println(100.0 / 3.0);  // 33.333333333333336
System.out.println(0.1 + 0.2);    // 0.30000000000000004

整数値を扱う問題では double を使わず long を使うようにしましょう。

型変換 (キャスト)

ある型の値を別の型に変換することを「キャスト」といいます。(型) を前に付けることで変換できます。

java
int a = 7;
double b = (double) a / 2;  // int を double に変換してから割る → 3.5
int c = (int) b;            // double を int に変換 (小数点以下切り捨て) → 3

System.out.println(b);  // 3.5
System.out.println(c);  // 3

int a(double) a とすることで double として扱い、7.0 / 2 = 3.5 という計算ができます。

複合代入演算子

変数を使って計算した結果を同じ変数に代入するパターンが頻繁に出てきます。このために「複合代入演算子」が用意されています。

演算子等価な式
+=x += 3x = x + 3
-=x -= 3x = x - 3
*=x *= 3x = x * 3
/=x /= 3x = x / 3
%=x %= 3x = x % 3
java
int x = 2;
x += 5;   // x = 2 + 5 = 7
x *= 3;   // x = 7 * 3 = 21
x /= 2;   // x = 21 / 2 = 10 (整数除算)
x %= 3;   // x = 10 % 3 = 1
x -= 1;   // x = 1 - 1 = 0
System.out.println(x);  // 0

インクリメント・デクリメント

変数を 1 増やす・減らす操作は頻繁に行うため、専用の演算子があります。

java
int x = 5;
x++;  // x = x + 1 と同じ → 6
x--;  // x = x - 1 と同じ → 5
System.out.println(x);  // 5

String と数値の変換

文字列と数値を相互に変換する方法です。

java
// String → int
String s = "123";
int n = Integer.parseInt(s);  // 123

// int → String
int m = 456;
String t = String.valueOf(m);  // "456"
// または
String u = Integer.toString(m); // "456"

練習問題

EX4. ◯年は何秒?


1.05. 入力

キーポイント

  • Scanner クラスを使って入力を受け取る
  • sc.nextInt() で整数、sc.nextDouble() で浮動小数点、sc.next() で文字列 (スペース区切り)
  • sc.nextLine() で1行全体を読み込む

Scanner の基本

競技プログラミングでは、プログラムに外部からデータを渡す「入力」が必要です。Java では Scanner クラスを使って標準入力からデータを読み込みます。

Scanner を使うには最初に import java.util.Scanner; と書く必要があります。

文字列の入力:

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();  // 1行全体を文字列として読み込む
        System.out.println(s);
        System.out.println(s);
        System.out.println(s);
    }
}

入力: Javaだいすき出力:

Javaだいすき
Javaだいすき
Javaだいすき

Scanner sc = new Scanner(System.in); で入力を読み込む準備をします。sc.nextLine() で1行を文字列として読み込み、変数 s に代入します。同じ変数を3回出力しているので、同じ文字列が3行表示されます。

整数の入力

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int a = sc.nextInt();      // 整数を読み込む
        System.out.println(a * 10);
    }
}

入力: 5出力: 50

sc.nextInt() は入力から整数を1つ読み込みます。読み込んだ値を変数 a に代入し、a * 10 を計算して出力しています。

浮動小数点の入力

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        double a = sc.nextDouble();
        System.out.println(a * 10);
    }
}

入力: 3.14出力: 31.400000000000002

浮動小数点の誤差により、出力が 31.4 にはならないことがあります。

複数の値の入力

sc.next() はスペースや改行で区切られた次のトークン (単語) を読み込みます。sc.nextInt() も同様にスペースや改行をスキップして次の整数を読みます。

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.next();    // スペースや改行で区切られた次の文字列
        int a = sc.nextInt();    // 次の整数
        System.out.println(s + " " + a * 10);
    }
}

入力:

Hello
5

出力: Hello 50

スペース区切りで複数の整数を入力

1行にスペース区切りで複数の整数が並んでいる場合も、nextInt() を繰り返し呼ぶだけで読み込めます。

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int a = sc.nextInt();
        int b = sc.nextInt();
        int c = sc.nextInt();
        System.out.println(a * 10);
        System.out.println(b * 100);
        System.out.println(c * 1000);
    }
}

入力: 10 20 30出力:

100
2000
30000

nextInt() はスペースや改行を自動的にスキップして次の整数を読み込みます。そのため、値が1行に並んでいても複数行に分かれていても同じコードで読み込むことができます。

高速入力 (BufferedReader)

Scanner は便利ですが、大量の入力を処理する場合は遅くなることがあります。その場合は BufferedReader を使います。

java
import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int a = Integer.parseInt(st.nextToken());
        int b = Integer.parseInt(st.nextToken());
        System.out.println(a + b);
    }
}

最初のうちは Scanner を使えば十分です。TLE (実行時間制限超過) が起きた場合に BufferedReader への切り替えを検討してください。

練習問題

EX5. A足すB問題


1.06. if文・比較演算子・論理演算子

キーポイント

  • if / else if / else で条件分岐
  • 比較演算子: ==, !=, >, <, >=, <=
  • 論理演算子: ! (否定), && (AND), || (OR)
  • Python の and/or/not はそれぞれ &&/||/! に対応
  • 連鎖比較 0 <= x <= 100 はできない → 0 <= x && x <= 100 と書く

条件分岐とは

「指定した条件に当てはまるときだけ処理をする」というのが条件分岐です。Java では if 文を使います。

比較演算子

比較演算子は2つの値を比較し、結果を true または false で返します。

演算子意味
x == yx と y が等しい
x != yx と y が等しくない
x > yx は y より大きい
x < yx は y より小さい
x >= yx は y 以上
x <= yx は y 以下

論理演算子

複数の条件を組み合わせるときに使います。

演算子意味Python の対応
!条件式否定 (条件が true なら false、false なら true)not
条件式1 && 条件式2両方が true のとき trueand
条件式1 || 条件式2少なくとも一方が true のとき trueor

基本的な if 文

if (条件式) { 処理 } の形で書きます。条件式が true のときだけ {} 内の処理が実行されます。

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int x = sc.nextInt();

        if (x < 10) {
            System.out.println("x は 10 より小さい");
        }

        System.out.println("終了");
    }
}

入力が 5 のとき:

x は 10 より小さい
終了

入力が 15 のとき:

終了

入力が 5 のとき 5 < 10true なので if 内の処理が実行されます。入力が 15 のとき 15 < 10false なので if 内の処理はスキップされます。

複数の if 文

複数の if 文を並べることで、複数の条件を独立してチェックできます。

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int x = sc.nextInt();

        if (x < 10) {
            System.out.println("x は 10 より小さい");
        }
        if (x >= 20) {
            System.out.println("x は 20 以上");
        }
        if (x == 5) {
            System.out.println("x は 5");
        }
        if (x != 100) {
            System.out.println("x は 100 ではない");
        }

        System.out.println("終了");
    }
}

入力が 5 のとき:

x は 10 より小さい
x は 5
x は 100 ではない
終了

4つの if 文がそれぞれ独立してチェックされるため、複数の条件を同時に満たす場合は複数のメッセージが出力されます。

論理演算子の使用例

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int x = sc.nextInt();
        int y = sc.nextInt();

        if (!(x == y)) {
            System.out.println("x と y は等しくない");
        }
        if (x == 10 && y == 10) {
            System.out.println("x と y は両方とも 10");
        }
        if (x == 0 || y == 0) {
            System.out.println("x か y の少なくともどちらかは 0");
        }

        System.out.println("終了");
    }
}

else 節

「条件が true のときは処理A、そうでなければ処理B」というパターンには else を使います。

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int x = sc.nextInt();

        if (x < 10) {
            System.out.println("x は 10 より小さい");
        } else {
            System.out.println("x は 10 より小さくない");
        }
    }
}

if の条件が false のとき、else 内の処理が実行されます。

else if チェーン

複数の条件を順番にチェックするには else if を使います。上から順にチェックして、最初に true になった条件のブロックだけが実行されます。

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int x = sc.nextInt();

        if (x < 10) {
            System.out.println("x は 10 より小さい");
        } else if (x > 20) {
            System.out.println("x は 10 より小さくなくて、20 より大きい");
        } else if (x == 15) {
            System.out.println("x は 10 以上 20 以下で、15 である");
        } else {
            System.out.println("x は 10 以上 20 以下で、15 でもない");
        }
    }
}

入力が 5 → 最初の iftrue"x は 10 より小さい" を出力

入力が 25 → 最初の iffalse、次の else iftrue"x は 10 より小さくなくて、20 より大きい" を出力

入力が 15 → 最初と2番目は false、3番目の else iftrue"x は 10 以上 20 以下で、15 である" を出力

ネストした if 文

if 文の中にさらに if 文を書くことができます。

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int x = sc.nextInt();

        if (x % 2 == 0) {
            if (x % 3 == 0) {
                System.out.println("x は 2 の倍数でも 3 の倍数でもある");
            } else {
                System.out.println("x は 2 の倍数ではあるが 3 の倍数ではない");
            }
        } else {
            if (x % 3 == 0) {
                System.out.println("x は 2 の倍数ではないが 3 の倍数ではある");
            } else {
                System.out.println("x は 2 の倍数でも 3 の倍数でもない");
            }
        }
    }
}

x = 6 のとき: 6 % 2 == 0true → 内側の if6 % 3 == 0true → 「2の倍数でも3の倍数でもある」

範囲チェック (連鎖比較の代替)

Python では 0 <= x <= 100 と書けますが、Java ではこの書き方はできません。&& を使って書きます。

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int x = sc.nextInt();

        if (0 <= x && x <= 100) {
            System.out.println("x は 0 以上 100 以下です");
        } else {
            System.out.println("x は 0 以上 100 以下ではありません");
        }
    }
}

0 <= x && x <= 100 は「x が 0 以上」かつ「x が 100 以下」という2つの条件を && で結んでいます。

練習問題

EX6. 電卓をつくろう


1.07. 論理式の値と boolean 型

キーポイント

  • 条件式の評価結果は boolean 型 (true / false)
  • Python の True/False に対応するが、truthy/falsy の概念はない
  • 数値の 0false に変換できない (コンパイルエラーになる)
  • boolean 変数は &&||! で操作できる

boolean 型とは

boolean (ブーリアン) 型は true (真) か false (偽) の2つの値だけをとるデータ型です。比較演算子や論理演算子の結果がこの型になります。

Python の True/False に対応しますが、Java には Python のような「truthy/falsy」の概念がありません。数値の 0if の条件に使うとコンパイルエラーになります。

条件式の評価結果

条件式を書くと、その評価結果は boolean 型の値になります。

java
public class Main {
    public static void main(String[] args) {
        int x = 0;
        System.out.println(x == 0);  // true
        System.out.println(x >= 1);  // false
    }
}

実行結果:

true
false

x == 0 は「x0 と等しいか?」という条件式で、x = 0 のとき true を返します。

boolean 変数

条件式の結果を boolean 型の変数に格納できます。

java
public class Main {
    public static void main(String[] args) {
        int x = 5;
        boolean a = (0 <= x);       // 0 <= 5 → true
        boolean b = (x <= 10);      // 5 <= 10 → true
        boolean c = a && b;         // true && true → true
        System.out.println(a + " " + b + " " + c);  // true true true
    }
}

実行結果:

true true true

ab をそれぞれ別の boolean 変数に格納し、c = a && b でその AND をとっています。

boolean 型を if 文で使う

boolean 型の変数を直接 if の条件に使えます。

java
public class Main {
    public static void main(String[] args) {
        if (true) {
            System.out.println("条件を満たした");
        }
        if (false) {
            System.out.println("表示されない");
        } else {
            System.out.println("条件を満たさなかった");
        }
    }
}

実行結果:

条件を満たした
条件を満たさなかった

Python との違い: truthy/falsy がない

Python では if 10:if "hello": のように、0以外の数値や空でない文字列が true として扱われます (truthy/falsy)。しかし Java では boolean 値のみが使えます。

java
// コンパイルエラーになる例
// if (10) { }          // エラー: int を boolean として使えない
// if ("hello") { }     // エラー

// 正しい書き方
if (10 != 0) { System.out.println("0でない"); }
String str = "hello";
if (!str.isEmpty()) { System.out.println("空でない"); }

boolean 変数の実用例

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int x = sc.nextInt();
        int y = sc.nextInt();

        boolean isEqual = (x == y);
        boolean isBothPositive = (x > 0) && (y > 0);
        boolean isEitherZero = (x == 0) || (y == 0);

        System.out.println("等しい: " + isEqual);
        System.out.println("両方正: " + isBothPositive);
        System.out.println("どちらか0: " + isEitherZero);
    }
}

練習問題

EX7. boolean値パズル


1.08. while 文

キーポイント

  • while (条件式) { 処理 } で繰り返し処理
  • 条件式が true である間、処理を繰り返し続ける
  • カウンタ変数を使った while (i < N) パターンが基本
  • Python と構文がほぼ同じ (インデントの代わりに {} を使う)

while 文とは

「条件が成立している間、処理を繰り返す」というのが while 文です。同じ処理を何度も繰り返すことを「ループ」といいます。

基本構文

java
while (条件式) {
    処理
}

while の丸括弧内の条件式が true の間、{} 内の処理が繰り返されます。処理が終わるたびに条件式が再評価されます。

カウンタ変数を使った基本パターン:

java
int i = 0;
while (i < N) {
    // 繰り返したい処理
    i++;  // カウンタを増やす (忘れると無限ループになる)
}

無限ループ

条件式に true を書くと、永遠にループします。break 文で抜けない限り終了しません。

java
while (true) {
    System.out.println("Hello");
    System.out.println("AtCoder");
}

このプログラムを実行するとプログラムが終了しないまま動き続けます。

カウントアップ

i を 0 から始めて 1 ずつ増やしながら N 回処理するパターンです。

java
public class Main {
    public static void main(String[] args) {
        int i = 0;
        while (i < 5) {
            System.out.println("Hello");
            i++;
        }
    }
}

実行結果:

Hello
Hello
Hello
Hello
Hello

このプログラムの流れ:

  1. i = 00 < 5true"Hello" を出力 → i を 1 に
  2. i = 11 < 5true"Hello" を出力 → i を 2 に
  3. i = 22 < 5true"Hello" を出力 → i を 3 に
  4. i = 33 < 5true"Hello" を出力 → i を 4 に
  5. i = 44 < 5true"Hello" を出力 → i を 5 に
  6. i = 55 < 5false → ループ終了

実践例: N個の整数の合計

N 個の整数を入力から読み込み、合計を計算するプログラムです。

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();  // 個数を読み込む
        int s = 0;             // 合計 (最初は0)
        int i = 0;
        while (i < N) {
            int x = sc.nextInt();  // 値を1つ読み込む
            s += x;               // 合計に加える
            i++;
        }
        System.out.println(s);
    }
}

入力:

3
1
10
100

出力: 111

N = 3 のとき: 1回目で s = 0 + 1 = 1、2回目で s = 1 + 10 = 11、3回目で s = 11 + 100 = 111

2ずつ増やすループ

ループの増分は1に限りません。

java
int i = 0;
while (i < 10) {
    System.out.println(i);
    i += 2;  // 2ずつ増やす
}

実行結果:

0
2
4
6
8

逆順ループ

大きい値から小さい値に向かってカウントダウンすることもできます。

java
int i = 5;
while (i >= 0) {
    System.out.println(i);
    i--;  // 1ずつ減らす
}

実行結果:

5
4
3
2
1
0

練習問題

EX8. たくさんのA足すB問題


1.09. for 文・break・continue

キーポイント

  • for (初期化; 条件式; 更新) { 処理 } が基本構文
  • N回繰り返すなら for (int i = 0; i < N; i++)
  • break でループを抜ける
  • continue で残りの処理をスキップして次のループへ
  • Python の for x in range(N)for (int i = 0; i < N; i++) に対応

for 文とは

while 文でカウンタ変数を使うパターンをより簡潔に書けるのが for 文です。

while 文:

java
int i = 0;      // 初期化
while (i < 5) { // 条件式
    処理
    i++;        // 更新
}

for 文 (同じ意味):

java
for (int i = 0; i < 5; i++) {
    処理
}

for (初期化; 条件式; 更新) という形で、while 文の3つの要素をまとめて書けます。

for 文の基本

java
public class Main {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            System.out.println(i);
        }
    }
}

実行結果:

0
1
2
3
4

i は 0 から始まり、i < 5true の間ループし、各繰り返しの最後に i++ が実行されます。したがって i は 0, 1, 2, 3, 4 と変化し、i = 5 になったときループが終了します。

Python の for i in range(5): と対応します。

range(a, b) の代わり

Python の for i in range(2, 5):i が 2, 3, 4 と変化します。Java では:

java
for (int i = 2; i < 5; i++) {
    System.out.println(i);
}

実行結果:

2
3
4

break

break は現在のループを即座に終了します。

java
public class Main {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            if (i == 3) {
                System.out.println("ぬける");
                break;  // ループを終了
            }
            System.out.println(i);
        }
        System.out.println("終了");
    }
}

実行結果:

0
1
2
ぬける
終了

i = 3 のとき if (i == 3)true になり、"ぬける" を出力してから break でループを終了します。i = 3, 4 のときの処理はスキップされます。

continue

continue はそのイテレーションの残りの処理をスキップして、次のイテレーションに進みます。

java
public class Main {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            if (i == 3) {
                System.out.println("とばす");
                continue;  // 残りをスキップして次のループへ
            }
            System.out.println(i);
        }
        System.out.println("終了");
    }
}

実行結果:

0
1
2
とばす
4
終了

i = 3 のとき continue が実行され、その後の System.out.println(i) はスキップされます。ただしループ自体は続き、i = 4 の処理が実行されます。break との違いに注意してください。

2ずつ増やすループ

Python の for i in range(0, 10, 2): は:

java
for (int i = 0; i < 10; i += 2) {
    System.out.println(i);
}

実行結果:

0
2
4
6
8

逆順ループ

Python の for i in range(5, -1, -1): は:

java
for (int i = 5; i >= 0; i--) {
    System.out.println(i);
}

実行結果:

5
4
3
2
1
0

練習問題

EX9. 電卓をつくろう2


1.10. 配列 (リスト)

キーポイント

  • Java の配列は宣言時にサイズが固定される: int[] a = new int[N]
  • 可変長のリストには ArrayList<Integer> を使う
  • インデックスは 0 から始まる
  • a.length で配列の長さを取得 (ArrayList の場合は list.size())
  • 配列の入力: for ループで sc.nextInt() を繰り返す

配列とは

複数の値をまとめて扱いたいときに使うのが「配列」です。Python の「リスト」に対応しますが、Java の配列はサイズが固定されているという違いがあります。

配列の基本

初期値を指定して配列を作成する方法:

java
int[] a = {3, 1, 4, 1, 5};  // 5要素の配列

System.out.println(a.length);  // 5 (要素数)
System.out.println(a[0]);      // 3 (インデックス0の要素)
System.out.println(a[2]);      // 4 (インデックス2の要素)

// 要素の変更
a[2] = 7;
System.out.println(a[2]);  // 7

実行結果:

5
3
4
7

インデックスは 0 から始まります。a[0] が最初の要素、a[4] が最後の要素です。

サイズ指定で配列を作成

要素数だけ決めて、後から値を入れることもできます。整数型の配列は自動的に 0 で初期化されます。

java
int N = 5;
int[] a = new int[N];  // 要素が {0, 0, 0, 0, 0} の配列が作られる

for ループで配列を処理

インデックス付きの for ループで全要素を処理できます。

java
int[] a = {3, 1, 4, 1, 5};
for (int i = 0; i < a.length; i++) {
    System.out.println(i + " : " + a[i]);
}

実行結果:

0 : 3
1 : 1
2 : 4
3 : 1
4 : 5

a.length は配列の要素数を返します。i は 0, 1, 2, 3, 4 と変化し、各インデックスの要素を表示しています。

拡張 for 文 (foreach)

値だけを順番に処理したい場合は「拡張 for 文」が使えます。Python の for x in a: に対応します。

java
int[] a = {3, 1, 4, 1, 5};
for (int x : a) {
    System.out.println(x);
}

実行結果:

3
1
4
1
5

for (int x : a) は「配列 a の各要素を x として順番に処理する」という意味です。

入力から配列を作成

N 個の整数を読み込んで配列に格納するパターンは非常によく使います。

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();        // 要素数を読み込む
        int[] a = new int[N];        // N要素の配列を作成
        for (int i = 0; i < N; i++) {
            a[i] = sc.nextInt();     // 各要素を読み込む
        }
        // スペース区切りで出力
        for (int i = 0; i < N; i++) {
            if (i > 0) System.out.print(" ");
            System.out.print(a[i]);
        }
        System.out.println();
    }
}

例題: 数学と英語のテストの合計点

N 人の数学 (M[i]) と英語 (E[i]) の点数が与えられ、各人の合計点を出力する問題です。

java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        int[] M = new int[N];
        int[] E = new int[N];

        for (int i = 0; i < N; i++) M[i] = sc.nextInt();
        for (int i = 0; i < N; i++) E[i] = sc.nextInt();

        for (int i = 0; i < N; i++) {
            System.out.println(M[i] + E[i]);
        }
    }
}

入力:

3
20 100 30
100 5 40

出力:

120
105
70

まず N = 3 を読み込み、M[] に 20, 100, 30、E[] に 100, 5, 40 を格納します。その後 M[0]+E[0]=120, M[1]+E[1]=105, M[2]+E[2]=70 を出力します。

ArrayList (可変長リスト)

Java の通常の配列はサイズが固定ですが、ArrayList を使うと要素を動的に追加・削除できます。Python のリストに近い挙動です。

java
import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();

        list.add(1);      // [1]
        list.add(2);      // [1, 2]
        list.add(3);      // [1, 2, 3]

        System.out.println(list.size());  // 3 (要素数)
        System.out.println(list.get(0));  // 1 (0番目の要素)

        list.set(1, 20);  // インデックス1の要素を20に変更
        System.out.println(list.get(1));  // 20

        list.remove(list.size() - 1);  // 末尾の要素を削除
        System.out.println(list);       // [1, 20]
    }
}

ArrayList<Integer><Integer> は「整数を格納する ArrayList」という意味です。プリミティブ型 (int) ではなくラッパー型 (Integer) を使う点に注意してください。

ArrayList の主な操作

操作メソッド計算量
末尾に追加list.add(x)O(1)
インデックスで取得list.get(i)O(1)
インデックスで変更list.set(i, x)O(1)
末尾を削除list.remove(list.size()-1)O(1)
途中に挿入list.add(i, x)O(N)
途中を削除list.remove(i)O(N)
サイズ取得list.size()O(1)
要素を検索list.contains(x)O(N)

配列を逆順に出力

java
int[] a = {3, 1, 4, 1, 5};
for (int i = a.length - 1; i >= 0; i--) {
    System.out.println(a[i]);
}

実行結果:

5
1
4
1
3

a.length - 1 は最後のインデックス (= 4) です。そこから 0 まで 1 ずつ減らしながら逆順に出力します。

練習問題

EX10. 平均との差


1.11. 文字列

キーポイント

  • Java の String不変 (immutable): 作成後に変更できない
  • 文字へのアクセスは s.charAt(i) (Python の s[i])
  • 文字列の長さは s.length() (配列の a.length と違い括弧が必要)
  • 文字列の連結は + 演算子または StringBuilder
  • 文字列の比較は == ではなく .equals() を使う

文字列の基本

Java の文字列は String 型で表します。" (ダブルクォート) で囲みます。

java
String a = "ABCDEFG";
String b = "AtCoder";

エスケープシーケンス

特殊な文字を文字列の中で表現するときは「エスケープシーケンス」を使います。

記法意味
\n改行
\"ダブルクォート
\'シングルクォート
\\バックスラッシュ
\tタブ
java
System.out.println("Hello\nWorld");  // 改行して World を出力
System.out.println("She said \"Hi\"");  // ダブルクォートを出力

実行結果:

Hello
World
She said "Hi"

主な文字列操作

java
String s = "Hello, AtCoder!";

System.out.println(s.length());        // 15 (文字数)
System.out.println(s.charAt(0));       // H (0番目の文字)
System.out.println(s.charAt(7));       // A (7番目の文字)
System.out.println(s.indexOf("At"));   // 7 (最初に出現する位置)
System.out.println(s.contains("At"));  // true (含まれるかどうか)
System.out.println(s.substring(7));    // AtCoder! (7文字目以降)
System.out.println(s.substring(7, 14)); // AtCoder (7〜13文字目)
System.out.println(s.replace("At", "My")); // Hello, MyCoder!
System.out.println(s.toUpperCase());   // HELLO, ATCODER!
System.out.println(s.toLowerCase());   // hello, atcoder!

注意: 配列の長さは a.length (括弧なし)、文字列の長さは s.length() (括弧あり) です。紛らわしいので注意してください。

文字列の文字を1つずつ処理

インデックスを使ったループで各文字を取り出せます。

java
String s = "AtCoder";
for (int i = 0; i < s.length(); i++) {
    System.out.println(s.charAt(i));
}

拡張 for 文を使う場合は toCharArray()char の配列に変換します:

java
for (char c : s.toCharArray()) {
    System.out.println(c);
}

実行結果:

A
t
C
o
d
e
r

文字列の連結

+ 演算子で文字列を連結できます。数値も自動的に文字列に変換されます。

java
String s = "Hello";
String t = "World";
System.out.println(s + ", " + t + "!");  // Hello, World!

int n = 42;
System.out.println("Answer: " + n);  // Answer: 42

文字列の比較 (重要)

Java では文字列の比較に == を使ってはいけません。 == はオブジェクトの参照 (メモリアドレス) を比較するため、内容が同じでも false になる場合があります。文字列の内容を比較するには .equals() メソッドを使います。

java
String a = new String("Hello");
String b = new String("Hello");
System.out.println(a == b);       // false (参照が異なる場合)
System.out.println(a.equals(b));  // true (内容が等しい)

// Scanner で読んだ文字列との比較
Scanner sc = new Scanner(System.in);
String s = sc.next();
if (s.equals("Yes")) {
    System.out.println("一致!");
}

これは競技プログラミングでよくある間違いです。必ず .equals() を使ってください。

文字列の分割

split() メソッドで文字列を区切り文字で分割できます。

java
String s = "10 20 30";
String[] parts = s.split(" ");  // スペースで分割
for (String p : parts) {
    System.out.println(p);
}

実行結果:

10
20
30

整数として処理する場合は Integer.parseInt() で変換します:

java
for (String p : parts) {
    int val = Integer.parseInt(p);
    System.out.println(val * 2);
}

StringBuilder (効率的な文字列変更)

ループの中で文字列を繰り返し変更・連結する場合、String+ 演算子を使うと非効率です (毎回新しいオブジェクトが作られるため)。StringBuilder を使うと効率的に変更できます。

java
StringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append(", ");
sb.append("AtCoder");
sb.append("!");
System.out.println(sb.toString());  // Hello, AtCoder!

// 文字の変更
sb.setCharAt(0, 'h');
System.out.println(sb.toString());  // hello, AtCoder!

char 型と int の変換

char 型 (1文字) と int 型 (ASCII コード) は相互に変換できます。

java
char c = 'A';
int code = (int) c;        // 65 (A の ASCII コード)
char d = (char)(code + 1); // 'B' (B の ASCII コード = 66)
System.out.println(d);     // B

// 文字と 'a' の差でアルファベットのオフセットを求める
char ch = 'c';
int offset = ch - 'a';  // 2 (c は a から 2 番目)

文字列と数値の変換

java
// String → int
int n = Integer.parseInt("123");    // 123

// String → long
long m = Long.parseLong("123456789012");

// String → double
double d = Double.parseDouble("3.14");

// int → String
String s = String.valueOf(123);     // "123"
String t = Integer.toString(123);   // "123"

練習問題

EX11. 文字列の処理


1.12. 組み込み関数 (Math クラス・Arrays クラス)

キーポイント

  • Java では多くの関数が Math クラスのメソッドとして提供される
  • 配列の操作には Arrays クラス、コレクションの操作には Collections クラス
  • import java.util.* で多くのユーティリティが使える

Math クラス

Math クラスは java.lang パッケージに含まれているため、import なしで使えます。

java
// 絶対値
System.out.println(Math.abs(-3));   // 3
System.out.println(Math.abs(5));    // 5

// 最小値・最大値 (2値の比較)
System.out.println(Math.min(3, 7)); // 3
System.out.println(Math.max(3, 7)); // 7

// べき乗 (戻り値は double)
System.out.println(Math.pow(3, 4));      // 81.0
System.out.println((long)Math.pow(3, 4)); // 81 (long に変換)

// 平方根
System.out.println(Math.sqrt(16));   // 4.0

// 切り上げ・切り捨て・四捨五入
System.out.println(Math.ceil(3.2));   // 4.0 (切り上げ)
System.out.println(Math.floor(3.8));  // 3.0 (切り捨て)
System.out.println(Math.round(3.5));  // 4 (四捨五入)

複数値の最小・最大

Math.min()Math.max() は2つの値を比較します。3つ以上の場合は入れ子にします。

java
int a = 1, b = -5, c = 3;
int minVal = Math.min(a, Math.min(b, c));  // -5
int maxVal = Math.max(a, Math.max(b, c));  // 3

配列の合計・最大値・最小値

Java 標準には配列の合計を求める sum() 関数がないため、手動でループして計算します。

java
import java.util.Arrays;

int[] a = {1, 3, -5, 2};

// 合計 (ループで足す)
int sum = 0;
for (int x : a) sum += x;
System.out.println(sum);  // 1

// 最大値 (手動)
int maxVal = a[0];
for (int x : a) maxVal = Math.max(maxVal, x);
System.out.println(maxVal);  // 3

// Stream API を使う方法 (参考)
int maxStream = Arrays.stream(a).max().getAsInt();  // 3
int minStream = Arrays.stream(a).min().getAsInt();  // -5

Arrays クラス

Arrays クラスは配列を操作するための便利なメソッドを提供します。使うには import java.util.Arrays; が必要です。

java
import java.util.Arrays;

int[] a = {3, 1, 4, 1, 5};

// ソート (元の配列を昇順に変更する)
Arrays.sort(a);
System.out.println(Arrays.toString(a));  // [1, 1, 3, 4, 5]

// 配列の内容を文字列で表示 (デバッグに便利)
System.out.println(Arrays.toString(a));  // [1, 1, 3, 4, 5]

// 配列のコピー
int[] b = Arrays.copyOf(a, a.length);    // 配列全体をコピー
int[] c = Arrays.copyOfRange(a, 1, 3);  // インデックス1から2まで (2未満) をコピー

// 二分探索 (ソート済み配列に対して)
int idx = Arrays.binarySearch(a, 3);    // 3 の位置を返す

Collections クラス (ArrayList 向け)

ArrayList などのコレクションを操作するには Collections クラスを使います。

java
import java.util.*;

ArrayList<Integer> list = new ArrayList<>(Arrays.asList(3, 1, 4, 1, 5));

System.out.println(Collections.min(list));  // 1 (最小値)
System.out.println(Collections.max(list));  // 5 (最大値)

Collections.sort(list);               // 昇順ソート (in-place)
System.out.println(list);             // [1, 1, 3, 4, 5]

Collections.reverse(list);            // 逆順に並べ替え (in-place)
System.out.println(list);             // [5, 4, 3, 1, 1]

インデックスと値を一緒に処理

Python の enumerate() の代わりに、インデックス付きの for ループを使います。

java
int[] a = {10, 30, 20, 50, 40};
for (int i = 0; i < a.length; i++) {
    System.out.println(i + " " + a[i]);
}

実行結果:

0 10
1 30
2 20
3 50
4 40

練習問題

EX12. Find the Fastest Runner


1.13. 関数 (メソッド)

キーポイント

  • Java では関数を「メソッド」と呼ぶ
  • AtCoder では static メソッドとして定義する
  • 戻り値の型を明示的に宣言する (void は戻り値なし)
  • Java にはグローバル変数の概念があるが、static フィールドとして定義する
  • スコープ (変数の有効範囲) は {} のブロック単位

メソッドとは

同じ処理を何度も書かなくても済むように、処理をまとめて名前をつけたものを「メソッド」(Python では「関数」と呼ぶ) といいます。

Java のメソッドは main メソッドと同じクラス内に static を付けて定義します。定義する順序は問いません (main の前でも後でも OK)。

基本的なメソッド定義 (戻り値なし)

java
public class Main {
    // 戻り値なしのメソッド
    static void printNumbers() {
        System.out.println(1);
        System.out.println(2);
        System.out.println(3);
    }

    public static void main(String[] args) {
        printNumbers();  // 1, 2, 3 が出力される
        printNumbers();  // もう一度呼び出せる
    }
}

実行結果:

1
2
3
1
2
3

static void printNumbers() は「引数なし、戻り値なしのメソッド」です。void は「戻り値がない」ことを意味します。

引数をとるメソッド

引数 (パラメータ) を受け取るメソッドの書き方。引数の型と名前を指定します。

java
public class Main {
    static void addAndPrint(int a, int b) {
        System.out.println(a + b);
    }

    public static void main(String[] args) {
        addAndPrint(1, 2);   // 3
        addAndPrint(10, 20); // 30
    }
}

実行結果:

3
30

addAndPrint(1, 2) と呼ぶと、メソッド内の a = 1b = 2 となり、1 + 2 = 3 が出力されます。

戻り値があるメソッド

計算結果を返すメソッドには戻り値の型を指定し、return で値を返します。

java
public class Main {
    static int addOne(int a) {
        return a + 1;  // 計算結果を返す
    }

    public static void main(String[] args) {
        int two = addOne(1);            // 2 が返ってくる
        System.out.println(two);        // 2
        System.out.println(addOne(1) + 1); // addOne(1)=2、2+1=3
    }
}

実行結果:

2
3

addOne(1)1 + 1 = 2 を計算して返します。この戻り値を変数に格納したり、さらに計算に使ったりできます。

return の特性

return はメソッドをその場で終了させます。return 以降のコードは実行されません。

java
static int myMin(int a, int b) {
    if (a < b) {
        return a;  // a が小さければ a を返してメソッド終了
    }
    return b;      // そうでなければ b を返す
}

早期リターン (早めに return する) のパターン:

java
static void printIfSeven(int a) {
    if (a == 7) {
        System.out.println("a is 7");
        return;  // ここでメソッド終了
    }
    // a が 7 でないときだけここに到達する
    System.out.println("a is not 7");
}

スコープ (変数の有効範囲)

変数は宣言された {} ブロックの中でのみ有効です。これを「スコープ」といいます。

java
public class Main {
    static int addOne(int a) {
        int result = a + 1;  // result は addOne の中でのみ有効
        return result;
    }

    public static void main(String[] args) {
        System.out.println(addOne(1));  // 2
        // System.out.println(result);  // コンパイルエラー: result はここでは見えない
    }
}

static フィールド (グローバル変数に相当)

Python の global 変数に相当するものは、Java では static フィールド (クラス変数) として定義します。

java
public class Main {
    static int a = 0;  // クラスレベルで定義 = どのメソッドからでもアクセスできる

    static void updateA(int val) {
        a = val;  // Python と違い、global 宣言は不要
    }

    public static void main(String[] args) {
        System.out.println(a);  // 0
        updateA(1);
        System.out.println(a);  // 1
    }
}

Python では global a と宣言する必要がありましたが、Java の static フィールドはその宣言が不要です。

配列を引数に渡す

Java では配列はメソッドに参照渡しされます。つまり、メソッド内で配列の要素を変更すると、元の配列も変更されます (Python のリストと同じ挙動)。

java
public class Main {
    static void addToArray(int[] arr, int val) {
        arr[0] += val;  // arr は元の配列と同じものを指している
    }

    public static void main(String[] args) {
        int[] a = {1, 2, 3};
        addToArray(a, 10);
        System.out.println(a[0]);  // 11 (元の配列が変更されている)
    }
}

メソッドのオーバーロード

Java では同じ名前のメソッドを、引数の型・数が異なる形で複数定義できます。これを「オーバーロード」といい、Python のデフォルト引数の代替として使えます。

java
public class Main {
    static void func(int a) {
        System.out.println(a * 3);
    }

    static void func(int a, int start) {
        System.out.println((a + start) * 3);
    }

    public static void main(String[] args) {
        func(1);      // 1 * 3 = 3
        func(1, 10);  // (1 + 10) * 3 = 33
    }
}

実行結果:

3
33

Python の def func(a, start=0): に相当します。

再帰メソッド

メソッドが自分自身を呼び出すことを「再帰呼び出し」といいます。詳細は第2章で説明しますが、ここでは例だけ示します。

java
public class Main {
    static int factorial(int n) {
        if (n == 0) return 1;
        return n * factorial(n - 1);  // 自分自身を呼び出す
    }

    public static void main(String[] args) {
        System.out.println(factorial(5));  // 5! = 120
    }
}

練習問題

EX13. 三人兄弟へのプレゼント

APG4bPython の教材を Java 向けに書き直したものです。