コーディング · プログラミング言語
Java入門チュートリアル(初心者向け)
結論
Javaは静的型付けのオブジェクト指向言語で、バイトコードにコンパイルされ、どのOS上でもJava仮想マシン(JVM)で動作します。JDKをインストールし、クラスを Hello.java に保存して java Hello.java で実行します。クラスとオブジェクト、プリミティブ型と参照型、コレクションフレームワーク(List、Map、Set)、検査例外、そしてレコード、var、パターンマッチングといった新しい機能が中心的な内容です。
Javaとは何か、何に使われるか
Javaは1995年にSun Microsystemsが公開した言語で、現在はオープンなOpenJDKプロジェクトで開発され、Oracleが中心的な役割を担っています。「Write once, run anywhere(一度書けばどこでも動く)」が特徴で、コンパイラが生成したバイトコードをJVMがWindows、macOS、Linuxで実行します。大規模な業務システムのバックエンド(Spring Bootがよく使われます)、Androidアプリ(Kotlinと併用)、Apache KafkaやHadoopなどのビッグデータ基盤、多くのデスクトップ・組み込みシステムで使われています。新バージョンは6か月ごとにリリースされ、本番ではJava 21などの長期サポート(LTS)版を選ぶのが一般的です。
JDKのインストールと Hello, world の実行
JDK(Java Development Kit)をインストールします。Eclipse TemurinなどのOpenJDKビルドや、OracleのJDKが使えます。java -version で確認します。Javaのプログラムはすべてクラスの中に書き、実行は main から始まります。
public class Hello {
public static void main(String[] args) {
System.out.println("Hello, world");
}
}java Hello.java # run a single source file directly
# Hello, world
javac Hello.java # or compile to Hello.class first
java Helloファイル名は public クラスの名前と一致させる必要があります(class Hello なら Hello.java)。
変数と基本の型
Javaには、値として直接格納される8つのプリミティブ型と、参照型(String や配列などのオブジェクト)があります。すべての変数には固定の型があり、メソッド内では var を使うと初期値からコンパイラが型を推論します。
| 型 | サイズ | 例 |
|---|---|---|
int | 32ビット | int n = 42; |
long | 64ビット | long big = 10_000_000_000L; |
double | 64ビット浮動小数点数 | double pi = 3.14159; |
boolean | true/false | boolean ok = true; |
char | 16ビットのUTF-16単位 | char c = 'A'; |
byte, short, float | 8、16、32ビット | 使う機会は少なめ |
String | 参照 | String s = "hi"; |
int count = 7;
double avg = count / 2; // 3.0, integer division happens first
double avg2 = count / 2.0; // 3.5
var name = "Ada"; // inferred as String
String msg = name + " has " + count + " items";
System.out.println(msg); // Ada has 7 items
System.out.println(Integer.parseInt("12") + 1); // 13これはコードの断片です。このような文は main などのメソッドの中に書いてください。
制御構文
int score = 72;
if (score >= 90) {
System.out.println("A");
} else if (score >= 70) {
System.out.println("B"); // B
} else {
System.out.println("C");
}
for (int i = 0; i < 3; i++) {
System.out.println(i); // 0, 1, 2
}
String day = "SAT";
String kind = switch (day) { // switch expression
case "SAT", "SUN" -> "weekend";
default -> "weekday";
};
System.out.println(kind); // weekendJavaには while、do/while のほか、配列やコレクションを順に処理する拡張 for (String s : list) ループもあります。
メソッド、クラス、レコード
クラスはフィールド(データ)とメソッド(振る舞い)をまとめます。static メソッドはクラス自体に属し、それ以外のメソッドは new で作ったオブジェクトに対して呼び出します。record は不変のデータクラスを簡潔に宣言する方法で、コンストラクタ、アクセサ、equals、hashCode、toString をコンパイラが生成します。
public class Shapes {
static double square(double x) {
return x * x;
}
static class Counter {
private int value;
void increment() { value++; }
int get() { return value; }
}
record Point(int x, int y) {
double distance() { return Math.sqrt(x * x + y * y); }
}
public static void main(String[] args) {
System.out.println(square(4)); // 16.0
Counter c = new Counter();
c.increment();
c.increment();
System.out.println(c.get()); // 2
Point p = new Point(3, 4);
System.out.println(p + " " + p.distance()); // Point[x=3, y=4] 5.0
}
}クラスは親クラスを1つだけ継承(extends)でき、インターフェースは複数実装(implements)できます。フィールドは通常 private にして、メソッド経由でアクセスします。
コレクション:List、Map、Set
java.util のコレクションフレームワークは、サイズを変更できるデータ構造を提供します。コレクションはオブジェクトを保持するため、プリミティブ型は自動的にボクシングされます(int は Integer になります)。
import java.util.*;
public class Collections101 {
public static void main(String[] args) {
List<Integer> nums = new ArrayList<>(List.of(3, 1, 2));
nums.add(5);
Collections.sort(nums);
System.out.println(nums + " " + nums.get(0)); // [1, 2, 3, 5] 1
Map<String, Integer> ages = new HashMap<>();
ages.put("ann", 31);
ages.put("bob", 25);
System.out.println(ages.getOrDefault("zed", 0)); // 0
Set<String> tags = new TreeSet<>(List.of("b", "a", "b"));
System.out.println(tags); // [a, b]
List<Integer> evensSquared = nums.stream()
.filter(n -> n % 2 == 0)
.map(n -> n * n)
.toList();
System.out.println(evensSquared); // [4]
}
}最後の文はストリームとラムダ式を使っており、コレクションを変換する関数型のスタイルです。List.of は変更できないリストを作ります。変更したい場合は new ArrayList<>(...) で包みます。
特徴的な機能:静的型付け、インターフェース、パターンマッチング
インターフェースは多くのクラスが実装できる契約を定義するもので、Javaの設計の基礎です。現代のJavaにはパターンマッチングがあり、instanceof や switch で型の判定と変数の束縛を一度に行えます。シールドインターフェース(Java 17以降)は許可される実装をすべて列挙するため、switch がすべてのケースを網羅しているかをコンパイラが検査できます。
public class Areas {
sealed interface Shape permits Circle, Rect {}
record Circle(double r) implements Shape {}
record Rect(double w, double h) implements Shape {}
static double area(Shape s) {
return switch (s) {
case Circle c -> Math.PI * c.r() * c.r();
case Rect r -> r.w() * r.h();
};
}
public static void main(String[] args) {
System.out.println(area(new Rect(2, 3))); // 6.0
}
}このような switch のパターンマッチングは、Java 21 LTS以降で標準機能です。
例外処理
エラーは例外として扱われます。検査例外(IOException など)は捕捉するか throws で宣言する必要があります。非検査例外(NullPointerException のような RuntimeException のサブクラス)は不要です。try-with-resources は、ファイルや接続を自動的に閉じます。
import java.io.*;
import java.nio.file.*;
public class ReadFirst {
static int parseAge(String text) {
int age = Integer.parseInt(text); // may throw NumberFormatException
if (age < 0) throw new IllegalArgumentException("negative age");
return age;
}
public static void main(String[] args) {
try {
System.out.println(parseAge("abc"));
} catch (NumberFormatException e) {
System.out.println("not a number"); // not a number
}
try (BufferedReader in = Files.newBufferedReader(Path.of("notes.txt"))) {
System.out.println(in.readLine());
} catch (IOException e) {
System.out.println("cannot read: " + e.getMessage());
}
}
}小さな完成プログラム:単語カウンター
import java.io.IOException;
import java.nio.file.*;
import java.util.*;
public class WordCount {
public static void main(String[] args) throws IOException {
if (args.length != 1) {
System.err.println("usage: java WordCount.java FILE");
System.exit(1);
}
String text = Files.readString(Path.of(args[0])).toLowerCase();
Map<String, Integer> counts = new HashMap<>();
for (String word : text.split("[^a-z']+")) {
if (!word.isEmpty()) counts.merge(word, 1, Integer::sum);
}
counts.entrySet().stream()
.sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
.limit(5)
.forEach(e -> System.out.printf("%5d %s%n", e.getValue(), e.getKey()));
}
}java WordCount.java notes.txt で実行します。出現回数の多い単語を上位5件、回数とともに表示します。
初心者がよくやる間違い
- 整数の除算:
5 / 2は2です。2.5を得るには、どちらかをdoubleにします。 nullに対してメソッドを呼び出してNullPointerExceptionが発生する。nullをチェックするか、値がないかもしれない場合はOptionalを使います。List.ofで作ったリストを変更しようとして、UnsupportedOperationExceptionが発生する。- 配列や
Listのインデックスが0から始まることを忘れ、最後の要素がlength - 1にあることを見落とす。
次のステップ
公式のJava開発者向けサイトdev.javaの学習パスに沿って学び、Java SE APIドキュメントをリファレンスとして手元に開いておきましょう。ビルドツール(MavenまたはGradle)、JUnitによる単体テストを学び、続いてWebサービス向けのSpring Bootなどのフレームワークに進みます。同じくJVMで動くKotlinも、次に学ぶ言語として自然な選択です。
よくある質問
Javaは習得が難しいですか?
Javaは型を宣言し、コードをクラスの中に書く必要があるため、Pythonより記述が冗長になります。ただし規則は一貫しており、コンパイラが早い段階でミスを説明してくれます。多くの大学が最初の言語として採用しています。
JDKとJVMの違いは何ですか?
JVMはコンパイル済みのバイトコードを実行します。JDKは開発キット一式で、JVMに加えてコンパイラ javac、標準ライブラリ、各種ツールが含まれます。開発者がインストールするのはJDKです。
どのバージョンのJavaを学ぶべきですか?
Java 21やそれ以降のLTSなど、現行の長期サポート版を学びましょう。古いコードも新しいJVMで動くため、最新の知識は既存プロジェクトにも役立ちます。
JavaとJavaScriptは同じものですか?
いいえ。名前は似ていますが、型システム、実行環境、用途の異なる別々の言語です。
Javaはまだ使われていますか?
はい。業務システムのバックエンド、Android、データ基盤で、今でも最も使われている言語の一つです。