Javaの3大特徴
-
Write Once, Run Anywhere
・プラットフォーム独立性
・JVMがあれば、どの環境でも動作 -
JVM (Java Virtual Machine)
・バイトコードの実行
・メモリ管理
・ガベージコレクション -
オブジェクト指向
・カプセル化
・継承
・ポリモーフィズム
Javaエディション
-
Java SE (Standard Edition)
・基本的な開発環境
・デスクトップアプリケーション開発 -
Java EE (Enterprise Edition)
・Webアプリケーション開発
・大規模システム向け -
Java ME (Micro Edition)
・組み込みシステム向け
・モバイルデバイス向け
※EE、MEを使用するには、SEをインストールする必要がある。
ソースファイルの規則
// ファイル名: HelloWorld.java
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
ファイル名はクラス名.java
大文字小文字は厳密に区別
publicクラスのファイル名はクラス名と一致必須
半角英数字
コンパイルと実行
# コンパイル
javac HelloWorld.java
# 実行
java HelloWorld
変数とデータ型の規則
基本型と参照型がある
- 基本データ型:
8種類ある
// 整数型
- 整数型
byte: 8ビット (-128 ~ 127)
short: 16ビット
int: 32ビット(デフォルト)
long: 64ビット(接尾辞 L または l)
- 浮動小数点型
float: 32ビット(接尾辞 F または f)
double: 64ビット(デフォルト)
- 文字型
char: 16ビット Unicode文字
- 論理型
boolean: true または false
リテラルの記述例
// 整数リテラル
int decimal = 100; // 10進数
int octal = 0100; // 8進数
int hex = 0x100; // 16進数
long longNum = 100L; // long型
※小数部をもたない値で、10進数・8進数・16進数・2進数を表現
// 浮動小数点リテラル
float f = 3.14F;
double d = 3.14;
// 文字リテラル
char c1 = 'A';
char c2 = '\u0041'; // Unicode
// 文字列リテラル
String str = "Hello";
※ダブルクオート
// 論理値リテラル
boolean b1 = true;
boolean b2 = false;
//nullリテラル
参照型のデータを利用する際に「何も参照していない」
- 参照型
基本型以外すべての、クラス、配列、インターフェイスなど。
データ型 変数名;
変数名 = 値;
配列の宣言と使用
// 配列の宣言と初期化
int[] numbers = new int[5]; // 要素数を指定
int[] scores = {80, 90, 75, 85}; // 初期値を指定
// 配列の使用
System.out.println(scores.length); // 配列の長さ
System.out.println(scores[0]); // 最初の要素にアクセス
変数の宣言と使用
- 変数の命名規則
半角英数字、アンダースコア(_)、ドル記号($)のみ使用可
数字は1文字目に使用不可
予約語は使用不可
大文字小文字は区別される
変数宣言と初期化規則:
// ローカル変数
int number; // 宣言のみ
number = 10; // 初期化
int number = 20; // 宣言と初期化を同時に
System.out.println(number); // OK
int count;
// System.out.println(count); // エラー:初期化されていない
// 定数(final)
final int MAX_VALUE = 100; // 後で変更不可
final int MIN_VALUE; // ブランクfinal(コンストラクタで初期化必須)
// 配列
int[] numbers = new int[5]; // 配列の宣言と生成
int[] scores = {80, 90, 75, 85}; // 配列の初期化
int[][] matrix = new int[3][4]; // 多次元配列
演算子の優先順位と規則
- 算術演算子
int a = 10;
int b = 3;
System.out.println(a + b); // 13 (加算)
System.out.println(a - b); // 7 (減算)
System.out.println(a * b); // 30 (乗算)
System.out.println(a / b); // 3 (除算)
System.out.println(a % b); // 1 (剰余)
- インクリメント/デクリメント演算子
int x = 5;
System.out.println(x++); // 5 (出力後に加算)
System.out.println(++x); // 7 (加算後に出力)
System.out.println(x--); // 7 (出力後に減算)
System.out.println(--x); // 5 (減算後に出力)
- 代入演算子
int n = 10;
n += 5; // n = n + 5 と同じ
n *= 2; // n = n * 2 と同じ
n /= 3; // n = n / 3 と同じ
n %= 4; // n = n % 4 と同じ
- 比較演算子
int x = 10;
int y = 5;
System.out.println(x == y); // false (等しい)
System.out.println(x != y); // true (等しくない)
System.out.println(x > y); // true (より大きい)
System.out.println(x >= y); // true (以上)
System.out.println(x < y); // false (より小さい)
System.out.println(x <= y); // false (以下)
- 論理演算子
boolean a = true;
boolean b = false;
// AND演算子
System.out.println(a & b); // false (両方評価)
System.out.println(a && b); // false (ショートサーキット)
// OR演算子
System.out.println(a | b); // true (両方評価)
System.out.println(a || b); // true (ショートサーキット)
// XOR演算子
System.out.println(a ^ b); // true (排他的論理和)
// NOT演算子
System.out.println(!a); // false (論理否定)
&&と&の違い:&&は最初の条件がfalseなら二つ目は評価しない
||と|の違い:||は最初の条件がtrueなら二つ目は評価しない
if文の基本
int score = 85;
// 単純なif文
if (score >= 80) {
System.out.println("合格");
}
// if-else文
if (score >= 80) {
System.out.println("優秀");
} else {
System.out.println("もう少し");
}
// if-else if-else文
if (score >= 90) {
System.out.println("優");
} else if (score >= 80) {
System.out.println("良");
} else if (score >= 70) {
System.out.println("可");
} else {
System.out.println("不可");
}
- switch文
int day = 3;
switch (day) {
case 1:
System.out.println("月曜日");
break;
case 2:
System.out.println("火曜日");
break;
case 3:
System.out.println("水曜日");
break;
default:
System.out.println("その他の曜日");
}
breakを忘れると次のcaseに処理が流れる(フォールスルー)
switch式で使用できる型は限定的(byte, short, int, char, enum, String)
defaultの位置は任意(最後である必要はない)
- 試験の注意点
// 演算子の優先順位に注意
int result = 2 + 3 * 4; // 14 (乗算が先)
//インクリメント/デクリメントの位置による違い
int a = 5;
int b = ++a; // a=6, b=6
int c = a++; // a=7, c=6
//条件式でのnullチェック
String str = null;
// nullチェックを先に行う
if (str != null && str.length() > 0) {
System.out.println("文字列あり");
}
//switch文でのbreak忘れ
int value = 1;
switch (value) {
case 1: // breakがないと case 2 も実行される
System.out.println("One");
case 2:
System.out.println("Two");
break;
}
制御文の規則
- if文:
// 基本形
if (条件) {
// 処理
} else if (条件) {
// 処理
} else {
// 処理
}
// 注意点
if (value = 10) // コンパイルエラー(booleanを期待する箇所で代入式)
if (value == 10) // OK
switch文:
// 使用可能な型:byte, short, int, char, String, enum
switch (value) {
case 1:
// 処理
break; // breakを忘れると次のcaseに流れる
case 2:
// 処理
break;
default:
// 処理
}
// コンパイルエラーとなるケース
switch (1.5) {} // double型は使用不可
switch (new Object()) {} // オブジェクトは使用不可
ループ文:
// for文
for (初期化; 条件; 更新) {
// 処理
}
// カウンタによるループ
for (int i = 0; i < 5; i++) {
System.out.println("i = " + i);
}
// 複数の変数を使用
for (int i = 0, j = 10; i < j; i++, j--) {
System.out.println("i = " + i + ", j = " + j);
}
// 拡張for文
for (型 変数名 : 配列またはコレクション) {
// 処理
}
// 配列の場合
int[] numbers = {1, 2, 3, 4, 5};
for (int num : numbers) {
System.out.println(num);
}
// コレクションの場合
List<String> names = Arrays.asList("田中", "鈴木", "佐藤");
for (String name : names) {
System.out.println(name);
}
// while文
int count = 0;
while (count < 5) {
System.out.println("カウント: " + count);
count++;
}
// 無限ループの例
while (true) {
// 必ず抜け出す条件を入れる
if (条件) {
break; // ループを抜け出す
}
}
//基本的なdo-while文
int number = 1;
do {
System.out.println("数値: " + number);
number *= 2;
} while (number < 100);
// while文の場合(条件が最初からfalseなら実行されない)
int x = 10;
while (x < 5) {
System.out.println("実行されない");
}
// do-while文の場合(最低1回は実行される)
int y = 10;
do {
System.out.println("1回は実行される");
} while (y < 5);
// break, continue
for (int i = 0; i < 10; i++) {
if (i == 5) break; // ループを抜ける
if (i == 3) continue; // 次のループへ
}
// ループからの脱出
for (int i = 0; i < 10; i++) {
if (i == 5) {
break; // i が 5 になったらループを抜ける
}
System.out.println(i);
}
// ラベル付きbreak
outer:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (i * j == 4) {
break outer; // 外側のループまで抜ける
}
}
}
// 特定の繰り返しをスキップ
for (int i = 0; i < 5; i++) {
if (i == 2) {
continue; // i が 2 の時はスキップ
}
System.out.println(i);
}
// ラベル付きcontinue
outer:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (i * j == 2) {
continue outer; // 外側のループの次の繰り返しへ
}
}
}
// 九九の表を作る
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= 9; j++) {
System.out.printf("%3d", i * j);
}
System.out.println();
}
// 無限ループになってしまう例
for (int i = 0; i < 10; ) {
System.out.println(i);
// iをインクリメントし忘れ
}
// 条件式を間違える例
while (i != 10) {
// 浮動小数点数の比較は避ける
}
オブジェクトとは
// 社員を表すクラスの例
public class Employee {
// 属性(フィールド)
private String name; // 社員名
private int employeeId; // 社員番号
private double salary; // 給与
// 操作(メソッド)
public void work() {
System.out.println(name + "が働いています");
}
public void getSalary() {
System.out.println(salary + "円の給与が支払われました");
}
}
カプセル化
public class BankAccount {
// privateで外部からの直接アクセスを防ぐ
private double balance;
// publicメソッドで安全なアクセスを提供
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}
public void withdraw(double amount) {
if (amount > 0 && balance >= amount) {
balance -= amount;
}
}
public double getBalance() {
return balance;
}
}
クラスの定義
public class Car {
// フィールド
private String brand;
private String model;
private int year;
// コンストラクタ
public Car(String brand, String model, int year) {
this.brand = brand;
this.model = model;
this.year = year;
}
// メソッド
public void start() {
System.out.println("エンジン始動");
}
}
インスタンス化
// オブジェクトの生成
Car myCar = new Car("Toyota", "Prius", 2023);
Car friendsCar = new Car("Honda", "Civic", 2022);
// それぞれのオブジェクトは独自の状態を持つ
myCar.start();
friendsCar.start();
継承の基本
// スーパークラス
public class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
public void makeSound() {
System.out.println("何かの音を出す");
}
}
// サブクラス
public class Dog extends Animal {
public Dog(String name) {
super(name); // スーパークラスのコンストラクタを呼び出し
}
@Override
public void makeSound() {
System.out.println(name + "が「わんわん」と鳴く");
}
// サブクラス独自のメソッド
public void fetch() {
System.out.println(name + "がボールを取ってくる");
}
}
インターフェース
// インターフェースの定義
public interface Flyable {
void fly();
void land();
}
// インターフェースの実装
public class Bird extends Animal implements Flyable {
public Bird(String name) {
super(name);
}
@Override
public void fly() {
System.out.println(name + "が飛び立つ");
}
@Override
public void land() {
System.out.println(name + "が着地する");
}
}
ポリモフィズム
// ポリモフィズムの例
Animal dog = new Dog("ポチ");
Animal cat = new Cat("タマ");
// 同じmakeSound()メソッドでも、それぞれ異なる動作をする
dog.makeSound(); // "ポチが「わんわん」と鳴く"
cat.makeSound(); // "タマが「にゃーん」と鳴く"
よくある間違い
// 誤: privateメンバーは継承されない
private void someMethod() { }
// 誤: finalクラスは継承できない
final class Parent { }
class Child extends Parent { } // コンパイルエラー
クラスとオブジェクトの規則
- クラス定義:
// クラスの定義
public class ClassName {
// インスタンス変数(フィールド)
private int field1;
protected String field2;
public double field3;
// static変数(クラス変数)
private static int count;
// コンストラクタ
public ClassName() {
// デフォルトコンストラクタ
}
// オーバーロードされたコンストラクタ
public ClassName(int value) {
this.field1 = value;
}
// インスタンスメソッド
public void method1() {
// 処理
}
// staticメソッド
public static void method2() {
// 処理
}
}
- アクセス修飾子の範囲:
public // どこからでもアクセス可能
protected // 同じパッケージ内と継承先からアクセス可能
(default) // 同じパッケージ内からのみアクセス可能
private // 同じクラス内からのみアクセス可能
継承・ポリモーフィズム
- クラスの継承の基本:
class SuperClass { } // スーパークラス
class SubClass extends SuperClass { } // サブクラス
Javaは単一継承のみをサポート(複数のクラスを継承することはできない)
継承を指定しないクラスは暗黙的にjava.lang.Objectを継承
extendsキーワードを使用して継承を実現
- メソッドのオーバーライド
class Animal {
public void makeSound() {
System.out.println("...");
}
}
class Dog extends Animal {
@Override // オーバーライド宣言(推奨)
public void makeSound() {
System.out.println("わんわん");
}
}
オーバーライドのルール:
メソッド名と引数リストが完全に一致すること
戻り値は同じか、サブクラス型であること
アクセス修飾子は同じか、より緩いものであること
this と super キーワード
- thisの使用
public class Student {
private String name;
public Student(String name) {
this.name = name; // インスタンス変数への参照
}
public void printInfo() {
this.printName(); // 同クラスのメソッド呼び出し
}
}
- superの使用
class Child extends Parent {
public Child() {
super(); // 親クラスのコンストラクタ呼び出し
}
public void display() {
super.display(); // 親クラスのメソッド呼び出し
}
}
抽象クラスとインターフェース
abstract class Shape {
abstract double getArea(); // 抽象メソッド
public void display() { // 具象メソッド
System.out.println("面積: " + getArea());
}
}
特徴:
abstractキーワードを使用
インスタンス化不可
抽象メソッドと具象メソッドの両方を持てる
インターフェース
public interface Drawable {
void draw(); // 暗黙的にpublic abstract
// Java 8以降ではデフォルトメソッドも定義可能
default void print() {
System.out.println("描画します");
}
}
特徴:
すべてのメソッドは暗黙的にpublic abstract
変数は暗黙的にpublic static final
複数のインターフェースを実装可能
型変換とキャスト
- 基本データ型の型変換
// 暗黙的な型変換(小さい型から大きい型へ)
byte b = 10;
int i = b; // OK
// 明示的な型変換(キャスト)
int x = 130;
byte y = (byte)x; // キャストが必要
型変換の方向:
byte → short → int → long → float → double
char ↗
- 参照型の型変換
// アップキャスト(暗黙的)
Dog dog = new Dog();
Animal animal = dog;
// ダウンキャスト(明示的)
Animal animal = new Dog();
Dog dog = (Dog)animal;
パッケージとアクセス制御
- パッケージの定義と使用
// ファイル先頭でパッケージを宣言
package com.example.app;
// 他のパッケージのクラスをインポート
import java.util.ArrayList;
import java.util.List;
- アクセス修飾子の範囲
- public: どこからでもアクセス可能
- protected: 同じパッケージ内と継承したサブクラスからアクセス可能
- デフォルト(何も指定しない): 同じパッケージ内からのみアクセス可能
- private: 同じクラス内からのみアクセス可能
例外処理の規則
// 検査例外(チェック例外)
Exception
├── IOException
├── SQLException
└── ClassNotFoundException
// 非検査例外(実行時例外)
RuntimeException
├── NullPointerException
├── ArrayIndexOutOfBoundsException
└── ClassCastException
// try-catch-finally
try {
// 例外が発生する可能性のある処理
} catch (Exception e) {
// 例外処理
} finally {
// 必ず実行される処理
}
// マルチキャッチ
try {
// 処理
} catch (IOException | SQLException e) {
// 複数の例外をまとめて処理
}
// throw文
public void method() throws IOException {
if (条件) {
throw new IOException("エラーメッセージ");
}
}
Java APIの主要なクラス
- String操作:
String str = "Hello";
str.length(); // 文字列の長さ
str.charAt(0); // 指定位置の文字
str.substring(1, 4); // 部分文字列
str.indexOf("l"); // 文字の位置
str.equals("Hello"); // 文字列の比較
- StringBuilder:
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World"); // 文字列の追加
sb.insert(5, "!"); // 文字列の挿入
sb.delete(5, 6); // 文字列の削除
sb.reverse(); // 文字列の反転
- 配列操作:
Arrays.sort(array); // 配列のソート
Arrays.toString(array); // 配列の文字列表現
Arrays.copyOf(array, newLength); // 配列のコピー
コンパイルエラーが発生する主なケース
- 変数関連:
// 未初期化変数の使用
int x;
System.out.println(x); // コンパイルエラー
// final変数の再代入
final int MAX = 100;
MAX = 200; // コンパイルエラー
// 型の不一致
int num = "文字列"; // コンパイルエラー
- メソッド関連:
// 戻り値の型の不一致
int getNumber() {
return "文字列"; // コンパイルエラー
}
// 引数の型の不一致
void method(int x) {}
method("文字列"); // コンパイルエラー
- 修飾子関連:
// staticコンテキストでのthis使用
public static void method() {
this.field = 10; // コンパイルエラー
}
// インターフェースでのフィールド変更
interface MyInterface {
int value = 10;
value = 20; // コンパイルエラー(暗黙的にfinal)
}
- 継承関連:
// 複数クラスの継承
class Child extends Parent1, Parent2 {} // コンパイルエラー
// より制限的なアクセス修飾子へのオーバーライド
class Parent {
protected void method() {}
}
class Child extends Parent {
private void method() {} // コンパイルエラー
}
- 例外処理関連:
// 未チェックの検査例外
void method() {
throw new IOException(); // コンパイルエラー(throws宣言が必要)
}
// catch順序の誤り
try {
// 処理
} catch (Exception e) {
// 処理
} catch (IOException e) { // コンパイルエラー(到達不能なcatch)
// 処理
}