Java基礎知識の習得と実践

Javaの基本構造と実行フロー

Javaプログラムはmainメソッドから開始され、その中で定義されたコードのみが実行される。他のメソッドやクラスの呼び出しがある場合にのみ、その処理へ制御が移る。

ループ制御文の動作

  • break:現在のループを完全に終了する。
  • continue:現在のイテレーションをスキップし、次のループに進む。
  • return:メソッド内の処理を即座に終了し、以降のコードは実行されない。ループ内での宣言はループ外ではアクセスできない。

配列の導入(2023年10月26日)

配列は複数のデータを同一型で管理するために使用されるデータ構造。初期化時にサイズを固定し、インデックスによるアクセスが可能。

メソッドの設計原則

メソッドはクラス内部で定義できるが、他のメソッドの内部に別のメソッドを定義することはできない。メソッド間の呼び出しは可能。

オブジェクト指向プログラミングの基礎(2023年10月30日)

「JavaBean」と呼ばれるクラスは、特定の事象を表現するためのテンプレートであり、mainメソッドを持たない。テスト用のクラスでは、このクラスのインスタンスを作成し、プロパティを設定・操作する。

  • 一つのJavaファイルにはpublic修飾子をつけたクラスが一つしか存在できない。
  • すべてのフィールドはprivateで宣言し、外部からの直接アクセスを禁止。

コンストラクタの特徴

  • 戻り値がない(voidも指定不可)。
  • インスタンス生成時に自動的に呼び出される。
  • ユーザーがコンストラクタを定義しない場合、デフォルトの無引数コンストラクタが自動生成されるが、自作するとそれ以上は自動生成されない。
public class Student {
    private String name;
    
    public Student() {
        System.out.println("名前:" + name);
    }
    
    public Student(int age) {
        this.age = age;
    }
}

標準的なJavaBeanの実装パターン

  • すべてのフィールドをprivate化。
  • 無引数およびすべての引数を持つコンストラクタを提供。
  • 各フィールドに対してgetとsetメソッドを定義。

配列と入力処理(2023年11月1日)

インスタンスを格納する配列を作成する際、ループ内で新しいインスタンスを生成することが重要。同じインスタンスを繰り返し更新すると、意図しない結果になる。

for (int i = 0; i < arr.length; i++) {
    Goods item = new Goods();
    item.setId(scanner.next());
    arr[i] = item;
}

文字列の扱い(2023年11月2日)

  • 文字列は基本データ型ではなく、参照型(オブジェクト)。
  • 文字列リテラルは文字列プール(String Pool)に保存され、重複した値は同一アドレスを共有。
  • new String()で作成された文字列はヒープ領域に独立して確保され、プールとは関係ない。
  • 文字列の長さはlengthというフィールド、配列の長さも同様にlengthだが、メソッドではない。
  • char型の変数は算術演算や比較において自動的にint型に変換される。
  • 文字列の切り取りは元の文字列を変更せず、新しく文字列オブジェクトを返す。

文字列操作と正規表現(2023年11月6日~7日)

Javaはチェーン式のメソッド呼び出し(メソッドチェーン)をサポートしており、コードの可読性が向上する。

char[] chars = str.toCharArray(); // 文字列 → 文字配列

コレクションフレームワーク

コレクション(List、Setなど)は動的サイズ変更が可能。容量の上限を超えると自動的に拡張される。

変数の初期値

  • ローカル変数:初期値がなく、代入前に使用するとコンパイルエラー。
  • メンバー変数:クラスのフィールドとして定義されたもので、デフォルト値(0、false、nullなど)が自動的に割り当てられる。

staticキーワードの理解

  • static変数は、インスタンスの生成前でもクラス名でアクセス可能。すべてのインスタンスで共通の値を持つ。
  • staticメソッドは、インスタンスの状態に依存せず、ユーティリティメソッドとしてよく使われる。
  • 非静的メソッド内ではthisが有効だが、静的メソッド内ではthisを使用できない。
  • 静的メソッドから非静的メソッドを呼び出すことはできない(どのインスタンスか不明)。逆は可能。

継承と多態性(2023年11月14日)

Javaは単一継承のみをサポート。複数のクラスを継承することはできない。

アクセス修飾子と継承

  • privateなメソッドは、サブクラス内でも直接呼び出せないが、親クラスのpublicメソッドから間接的に呼び出せる。
  • メンバ変数はすべて継承されるが、privateなものは外部から直接アクセスできない。
  • コンストラクタは継承されない。ただし、super()を使って親クラスのコンストラクタを明示的に呼び出せる。

メソッドのオーバーライド

class Person {
    int age;
    String name;

    public Person() {
        System.out.println("親クラスの無引数コンストラクタ");
    }

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }
}

class Student extends Person {
    String id;

    public Student() {
        super(); // 親クラスのコンストラクタ呼び出し
        System.out.println("子クラスの無引数コンストラクタ");
    }

    public Student(int age, String name, String id) {
        super(age, name); // 親クラスの引数付きコンストラクタ呼び出し
        this.id = id;
    }
}

多態性の応用

多態性では、変数の型(左辺)が親クラスであっても、実際のインスタンスは子クラスである可能性がある。

Person p = new Student();
Student s = (Student) p; // 型キャストが必要
s.speak(); // 子クラス固有のメソッド呼び出し

安全なキャストにはinstanceofを使用:

if (p instanceof Student student) {
    student.speak();
} else if (p instanceof Teacher teacher) {
    teacher.teach();
}

抽象クラスとインターフェース

抽象クラスはインスタンス化できないが、staticメソッドは直接呼び出せる。抽象メソッドは実装が必須。

abstract class Animal {
    abstract void makeSound();
}

interface Swimmable {
    void swim();
}

クラスは複数のインターフェースを実装可能:

class Frog extends Animal implements Swimmable {
    @Override
    public void makeSound() {
        System.out.println("ガアガア");
    }

    @Override
    public void swim() {
        System.out.println("泳ぐ");
    }
}

インターフェースの拡張機能

  • staticメソッド:インターフェース自身から呼び出し可能。
  • defaultメソッド:実装クラスがオーバーライドしなくても使える。

内部クラスと匿名クラス

名前のないクラスを定義することができる。特にイベントリスナーなどでよく使われる。

new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        System.out.println("クリックされました");
    }
};

APIの活用

Mathクラス

System.out.println(Math.sqrt(4));   // 2.0
System.out.println(Math.cbrt(8));   // 2.0

BigIntegerとBigDecimal

  • BigInteger:任意精度の整数計算に適している。
  • BigDecimal:小数の正確な計算(金融計算など)に必要。除算では桁数と丸めモードを明示する必要がある。

正規表現(Regex)

文字列の検索・置換・分割に強力なツール。

String regex = "Java\\d{1,2}";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(text);

while (m.find()) {
    System.out.println(m.group()); // Java8, Java11, Java17 などが抽出
}

時間と日付の操作(2023年12月)

JDK 8以前の方法

  • Date:ミリ秒単位の時刻を表す。
  • SimpleDateFormat:フォーマットの定義と解析が可能。
  • Calendar:日付の細かい要素(年、月、日、曜日など)を個別に操作。

JDK 8以降の新クラス

  • LocalDateTime:時刻情報を持たない日付。
  • Duration:時間間隔の計算(秒、分、時間など)。
  • Period:年、月、日単位の期間。
  • ChronoUnit:さまざまな単位での差分計算。

ラッパークラスと自動変換

基本データ型をオブジェクトとして扱うために使用。JDK5以降では自動装箱(auto-boxing)と自動アンボクシング(auto-unboxing)がサポートされている。

Integer i = 10;         // 自動装箱
int j = i;              // 自動アンボクシング

入力処理のベストプラクティス

Scanner.nextLine()を使うことで、スペースや改行を含む一連の入力を取得できる。

Scanner sc = new Scanner(System.in);
String input = sc.nextLine();
double value = Double.parseDouble(input);

集合へのデータ追加(例)

1~100の整数を入力し、合計が200を超えるまで追加。

ArrayList<Integer> list = new ArrayList<>();
Scanner sc = new Scanner(System.in);

while (true) {
    System.out.print("整数を入力(1~100): ");
    String input = sc.nextLine();
    int num = Integer.parseInt(input);

    if (num < 1 || num > 100) {
        System.out.println("範囲外です。再入力してください。");
        continue;
    }

    list.add(num);
    int sum = list.stream().mapToInt(Integer::intValue).sum();

    if (sum > 200) {
        System.out.println("合計:" + sum + "(条件達成)");
        break;
    }
}

タグ: Java オブジェクト指向 コレクション 正規表現 日付処理

10月1日 01:52 投稿