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;
}
}