Java

#3
TIOBE#4
PYPL#2
GitHub#8
RedMonk#3
IEEESpectrum#2
JetBrains#5
プログラミング言語オブジェクト指向JVMエンタープライズAndroidクロスプラットフォーム

プログラミング言語

Java

概要

Javaは「一度書けばどこでも動く」をコンセプトとするオブジェクト指向プログラミング言語です。

詳細

Javaは1995年にSun Microsystems(現Oracle)によって開発されたオブジェクト指向プログラミング言語です。「Write Once, Run Anywhere」(WORA)の理念のもと、Java仮想マシン(JVM)上で動作することで、プラットフォームに依存しないアプリケーション開発を可能にしています。強い型付け、自動メモリ管理(ガベージコレクション)、豊富な標準ライブラリを特徴とし、エンタープライズ開発、Webアプリケーション、Androidアプリ開発、ビッグデータ処理など幅広い分野で使用されています。Oracle、IBM、Google、LinkedInなどの大手企業が重要なシステムでJavaを採用しており、安定性と信頼性の高さで知られています。

書き方の例

Hello World

// 基本的なHello World
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
        
        // 変数を使った出力
        String message = "こんにちは、Java!";
        System.out.println(message);
        
        // 文字列の連結
        String name = "太郎";
        int age = 25;
        System.out.println("私の名前は" + name + "で、" + age + "歳です。");
        
        // printf形式の出力
        System.out.printf("私の名前は%sで、%d歳です。%n", name, age);
    }
}

// パッケージを使用した例
package com.example.hello;

public class HelloJava {
    public static void main(String[] args) {
        System.out.println("Hello from Java package!");
    }
}

変数とデータ型

public class Variables {
    public static void main(String[] args) {
        // 基本データ型(プリミティブ型)
        int number = 42;
        long bigNumber = 1234567890L;
        float price = 99.99f;
        double pi = 3.14159;
        char initial = 'J';
        boolean isActive = true;
        byte smallNumber = 100;
        short mediumNumber = 30000;
        
        // 参照型
        String name = "田中太郎";
        String nullString = null;
        
        // 配列
        int[] numbers = {1, 2, 3, 4, 5};
        String[] names = new String[3];
        names[0] = "田中";
        names[1] = "山田";
        names[2] = "佐藤";
        
        // 定数(final)
        final double TAX_RATE = 0.1;
        final String COMPANY_NAME = "ABC株式会社";
        
        // 型推論(Java 10以降)
        var message = "これは文字列です"; // String型として推論
        var count = 10; // int型として推論
        var items = new String[]{"アイテム1", "アイテム2"}; // String[]型として推論
        
        // 出力例
        System.out.println("数値: " + number);
        System.out.println("大きな数値: " + bigNumber);
        System.out.println("価格: " + price);
        System.out.println("円周率: " + pi);
        System.out.println("初期文字: " + initial);
        System.out.println("アクティブ: " + isActive);
        System.out.println("名前: " + name);
        
        // 配列の出力
        System.out.println("数値配列: " + java.util.Arrays.toString(numbers));
        System.out.println("名前配列: " + java.util.Arrays.toString(names));
        
        // null チェック
        if (nullString == null) {
            System.out.println("nullStringはnullです");
        }
    }
}

メソッド

public class Methods {
    // 基本的なメソッド
    public static int add(int a, int b) {
        return a + b;
    }
    
    // メソッドオーバーロード
    public static double add(double a, double b) {
        return a + b;
    }
    
    public static String add(String a, String b) {
        return a + b;
    }
    
    // 可変長引数
    public static int sum(int... numbers) {
        int total = 0;
        for (int num : numbers) {
            total += num;
        }
        return total;
    }
    
    // 戻り値なしのメソッド
    public static void printMessage(String message) {
        System.out.println("メッセージ: " + message);
    }
    
    // 配列を引数とするメソッド
    public static void printArray(String[] array) {
        for (String item : array) {
            System.out.println("- " + item);
        }
    }
    
    // 再帰メソッド
    public static int factorial(int n) {
        if (n <= 1) {
            return 1;
        }
        return n * factorial(n - 1);
    }
    
    public static void main(String[] args) {
        // メソッドの呼び出し
        System.out.println("5 + 3 = " + add(5, 3));
        System.out.println("2.5 + 3.7 = " + add(2.5, 3.7));
        System.out.println("Hello + World = " + add("Hello", "World"));
        
        // 可変長引数
        System.out.println("合計: " + sum(1, 2, 3, 4, 5));
        System.out.println("合計: " + sum(10, 20));
        
        // 戻り値なしのメソッド
        printMessage("こんにちは、Java!");
        
        // 配列を渡す
        String[] fruits = {"りんご", "バナナ", "オレンジ"};
        printArray(fruits);
        
        // 再帰メソッド
        System.out.println("5の階乗: " + factorial(5));
    }
}

クラスとオブジェクト

// 基本的なクラス
class Person {
    // フィールド(プライベート)
    private String name;
    private int age;
    private String email;
    
    // コンストラクタ
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // オーバーロードされたコンストラクタ
    public Person(String name, int age, String email) {
        this(name, age); // 他のコンストラクタを呼び出し
        this.email = email;
    }
    
    // ゲッター
    public String getName() {
        return name;
    }
    
    public int getAge() {
        return age;
    }
    
    public String getEmail() {
        return email;
    }
    
    // セッター
    public void setAge(int age) {
        if (age >= 0) {
            this.age = age;
        }
    }
    
    public void setEmail(String email) {
        this.email = email;
    }
    
    // メソッド
    public void introduce() {
        System.out.println("私の名前は" + name + "で、" + age + "歳です。");
        if (email != null) {
            System.out.println("メールアドレス: " + email);
        }
    }
    
    // static メソッド
    public static Person createDefaultPerson() {
        return new Person("名前なし", 0);
    }
    
    // toString メソッドのオーバーライド
    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + ", email='" + email + "'}";
    }
}

// 抽象クラス
abstract class Animal {
    protected String name;
    
    public Animal(String name) {
        this.name = name;
    }
    
    public abstract void makeSound();
    
    public void sleep() {
        System.out.println(name + "は眠っています。");
    }
}

// 継承
class Dog extends Animal {
    private String breed;
    
    public Dog(String name, String breed) {
        super(name);
        this.breed = breed;
    }
    
    @Override
    public void makeSound() {
        System.out.println(name + "(" + breed + ")がワンワンと鳴いています。");
    }
    
    public void fetch() {
        System.out.println(name + "がボールを取ってきました。");
    }
}

// インターフェース
interface Drawable {
    void draw();
    
    // デフォルトメソッド(Java 8以降)
    default void info() {
        System.out.println("これは描画可能なオブジェクトです。");
    }
    
    // static メソッド(Java 8以降)
    static void showVersion() {
        System.out.println("Drawable interface v1.0");
    }
}

// インターフェースの実装
class Circle implements Drawable {
    private double radius;
    
    public Circle(double radius) {
        this.radius = radius;
    }
    
    @Override
    public void draw() {
        System.out.println("半径 " + radius + " の円を描画します。");
    }
    
    public double getArea() {
        return Math.PI * radius * radius;
    }
}

public class ClassExample {
    public static void main(String[] args) {
        // オブジェクトの作成
        Person person1 = new Person("田中太郎", 25);
        Person person2 = new Person("山田花子", 30, "[email protected]");
        
        // メソッドの呼び出し
        person1.introduce();
        person2.introduce();
        
        // セッターの使用
        person1.setEmail("[email protected]");
        person1.introduce();
        
        // toString の使用
        System.out.println(person1);
        
        // static メソッドの呼び出し
        Person defaultPerson = Person.createDefaultPerson();
        defaultPerson.introduce();
        
        // 継承の例
        Dog dog = new Dog("ポチ", "柴犬");
        dog.makeSound();
        dog.fetch();
        dog.sleep();
        
        // インターフェースの例
        Circle circle = new Circle(5.0);
        circle.draw();
        circle.info();
        System.out.println("円の面積: " + circle.getArea());
        
        // static メソッドの呼び出し
        Drawable.showVersion();
    }
}

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

import java.util.*;
import java.util.stream.Collectors;

public class Collections {
    public static void main(String[] args) {
        // ArrayList
        List<String> fruits = new ArrayList<>();
        fruits.add("りんご");
        fruits.add("バナナ");
        fruits.add("オレンジ");
        fruits.add("りんご"); // 重複可能
        
        System.out.println("フルーツリスト: " + fruits);
        System.out.println("最初の要素: " + fruits.get(0));
        System.out.println("サイズ: " + fruits.size());
        
        // 拡張for文(for-each)
        System.out.println("各フルーツ:");
        for (String fruit : fruits) {
            System.out.println("- " + fruit);
        }
        
        // HashSet(重複なし)
        Set<String> uniqueFruits = new HashSet<>(fruits);
        System.out.println("ユニークなフルーツ: " + uniqueFruits);
        
        // HashMap
        Map<String, Integer> fruitPrices = new HashMap<>();
        fruitPrices.put("りんご", 100);
        fruitPrices.put("バナナ", 80);
        fruitPrices.put("オレンジ", 120);
        
        System.out.println("フルーツの価格:");
        for (Map.Entry<String, Integer> entry : fruitPrices.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue() + "円");
        }
        
        // Stream API(Java 8以降)
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        
        // フィルタリング
        List<Integer> evenNumbers = numbers.stream()
            .filter(n -> n % 2 == 0)
            .collect(Collectors.toList());
        System.out.println("偶数: " + evenNumbers);
        
        // マッピング
        List<Integer> doubled = numbers.stream()
            .map(n -> n * 2)
            .collect(Collectors.toList());
        System.out.println("倍数: " + doubled);
        
        // 合計
        int sum = numbers.stream()
            .mapToInt(Integer::intValue)
            .sum();
        System.out.println("合計: " + sum);
        
        // 条件に一致する要素の検索
        Optional<String> expensiveFruit = fruitPrices.entrySet().stream()
            .filter(entry -> entry.getValue() > 100)
            .map(Map.Entry::getKey)
            .findFirst();
        
        if (expensiveFruit.isPresent()) {
            System.out.println("高価なフルーツ: " + expensiveFruit.get());
        }
        
        // グループ化
        List<String> words = Arrays.asList("apple", "banana", "apricot", "cherry", "avocado");
        Map<Character, List<String>> groupedWords = words.stream()
            .collect(Collectors.groupingBy(word -> word.charAt(0)));
        System.out.println("最初の文字でグループ化: " + groupedWords);
    }
}

例外処理

// カスタム例外クラス
class ValidationException extends Exception {
    public ValidationException(String message) {
        super(message);
    }
}

class AgeOutOfRangeException extends RuntimeException {
    public AgeOutOfRangeException(String message) {
        super(message);
    }
}

public class ExceptionHandling {
    // チェック例外をスローするメソッド
    public static void validateEmail(String email) throws ValidationException {
        if (email == null || !email.contains("@")) {
            throw new ValidationException("無効なメールアドレスです: " + email);
        }
    }
    
    // 非チェック例外をスローするメソッド
    public static void validateAge(int age) {
        if (age < 0 || age > 150) {
            throw new AgeOutOfRangeException("年齢は0から150の間である必要があります: " + age);
        }
    }
    
    public static int divide(int a, int b) {
        if (b == 0) {
            throw new ArithmeticException("ゼロで除算はできません");
        }
        return a / b;
    }
    
    public static void main(String[] args) {
        // try-catch文
        try {
            int result = divide(10, 2);
            System.out.println("10 ÷ 2 = " + result);
        } catch (ArithmeticException e) {
            System.out.println("算術エラー: " + e.getMessage());
        }
        
        // 複数の例外をキャッチ
        try {
            validateEmail("invalid-email");
        } catch (ValidationException e) {
            System.out.println("検証エラー: " + e.getMessage());
        }
        
        // 非チェック例外のキャッチ
        try {
            validateAge(-5);
        } catch (AgeOutOfRangeException e) {
            System.out.println("年齢エラー: " + e.getMessage());
        }
        
        // 複数の例外タイプを一度にキャッチ(Java 7以降)
        try {
            int[] array = {1, 2, 3};
            System.out.println(array[5]); // ArrayIndexOutOfBoundsException
        } catch (ArrayIndexOutOfBoundsException | NullPointerException e) {
            System.out.println("配列または null エラー: " + e.getMessage());
        }
        
        // finally句
        try {
            System.out.println("処理を実行中...");
            // 何らかの処理
        } catch (Exception e) {
            System.out.println("エラーが発生しました: " + e.getMessage());
        } finally {
            System.out.println("cleanup処理(必ず実行される)");
        }
        
        // try-with-resources(Java 7以降)
        try (Scanner scanner = new Scanner(System.in)) {
            // リソースが自動的にクローズされる
            System.out.println("Scanner が自動的にクローズされます");
        } catch (Exception e) {
            System.out.println("Scanner エラー: " + e.getMessage());
        }
        
        // throw文を使った例外の再スロー
        try {
            handleException();
        } catch (Exception e) {
            System.out.println("キャッチされた例外: " + e.getMessage());
        }
    }
    
    private static void handleException() throws Exception {
        try {
            divide(10, 0);
        } catch (ArithmeticException e) {
            System.out.println("内部でキャッチ: " + e.getMessage());
            throw new Exception("処理に失敗しました", e); // 原因となる例外を保持
        }
    }
}

ジェネリクス

import java.util.*;

// ジェネリッククラス
class Box<T> {
    private T content;
    
    public void set(T content) {
        this.content = content;
    }
    
    public T get() {
        return content;
    }
    
    @Override
    public String toString() {
        return "Box{content=" + content + "}";
    }
}

// 複数の型パラメータ
class Pair<T, U> {
    private T first;
    private U second;
    
    public Pair(T first, U second) {
        this.first = first;
        this.second = second;
    }
    
    public T getFirst() { return first; }
    public U getSecond() { return second; }
    
    @Override
    public String toString() {
        return "Pair{first=" + first + ", second=" + second + "}";
    }
}

// 境界付き型パラメータ
class NumberBox<T extends Number> {
    private T number;
    
    public NumberBox(T number) {
        this.number = number;
    }
    
    public double getDoubleValue() {
        return number.doubleValue();
    }
}

public class Generics {
    // ジェネリックメソッド
    public static <T> void swap(T[] array, int i, int j) {
        T temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
    
    // 複数の型パラメータを持つジェネリックメソッド
    public static <T, U> void printPair(T first, U second) {
        System.out.println("ペア: " + first + " と " + second);
    }
    
    // ワイルドカード
    public static void printList(List<?> list) {
        for (Object item : list) {
            System.out.println("- " + item);
        }
    }
    
    // 上限境界ワイルドカード
    public static double sumOfNumbers(List<? extends Number> numbers) {
        double sum = 0.0;
        for (Number num : numbers) {
            sum += num.doubleValue();
        }
        return sum;
    }
    
    // 下限境界ワイルドカード
    public static void addNumbers(List<? super Integer> list) {
        list.add(1);
        list.add(2);
        list.add(3);
    }
    
    public static void main(String[] args) {
        // ジェネリッククラスの使用
        Box<String> stringBox = new Box<>();
        stringBox.set("Hello, Generics!");
        System.out.println("文字列ボックス: " + stringBox.get());
        
        Box<Integer> numberBox = new Box<>();
        numberBox.set(42);
        System.out.println("数値ボックス: " + numberBox.get());
        
        // 複数の型パラメータ
        Pair<String, Integer> nameAge = new Pair<>("田中", 25);
        System.out.println("名前と年齢: " + nameAge);
        
        // 境界付き型パラメータ
        NumberBox<Integer> intBox = new NumberBox<>(100);
        NumberBox<Double> doubleBox = new NumberBox<>(3.14);
        System.out.println("整数ボックス: " + intBox.getDoubleValue());
        System.out.println("実数ボックス: " + doubleBox.getDoubleValue());
        
        // ジェネリックメソッド
        String[] words = {"Hello", "World", "Java"};
        System.out.println("交換前: " + Arrays.toString(words));
        swap(words, 0, 2);
        System.out.println("交換後: " + Arrays.toString(words));
        
        // 複数の型パラメータ
        printPair("名前", "田中");
        printPair(100, 200);
        
        // ワイルドカード
        List<String> stringList = Arrays.asList("りんご", "バナナ", "オレンジ");
        List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5);
        
        System.out.println("文字列リスト:");
        printList(stringList);
        System.out.println("整数リスト:");
        printList(intList);
        
        // 上限境界ワイルドカード
        List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
        List<Double> doubles = Arrays.asList(1.1, 2.2, 3.3);
        
        System.out.println("整数の合計: " + sumOfNumbers(integers));
        System.out.println("実数の合計: " + sumOfNumbers(doubles));
        
        // 下限境界ワイルドカード
        List<Number> numbers = new ArrayList<>();
        addNumbers(numbers);
        System.out.println("追加された数値: " + numbers);
    }
}

バージョン

バージョン リリース日 主な新機能
Java 21 (LTS) 2023-09 Virtual Threads, Pattern Matching, Record Patterns
Java 17 (LTS) 2021-09 Sealed Classes, Pattern Matching for switch
Java 11 (LTS) 2018-09 Local-Variable Syntax for Lambda, HTTP Client API
Java 8 (LTS) 2014-03 Lambda Expressions, Stream API, Optional
Java 7 2011-07 Try-with-resources, Diamond operator
Java 6 2006-12 Scripting API, Compiler API
Java 5 2004-09 Generics, Annotations, Autoboxing

参考ページ

公式ドキュメント

学習リソース

開発ツール

  • IntelliJ IDEA - 人気のJava IDE
  • Eclipse - オープンソースJava IDE
  • Maven - プロジェクト管理・ビルドツール
  • Gradle - モダンなビルドツール