Java超|クラスライブラリとパッケージの関係

Javaのクラスライブラリは、悟空たちの任務を支える巨大な戦士本部の道具棚。パッケージという棚の場所を知れば、必要なクラスを迷わず取り出せます。

Javaでは、自分でクラスを作るだけでなく、Javaが最初から用意してくれている便利なクラスも使えます。

たとえば、文字列を扱う String、計算に使う Math、ファイルや文字の読み書きに使う BufferedReader、リスト管理に使う ArrayList などです。

これらは、毎回自分で一から作らなくても使える便利な部品です。
このような、あらかじめ用意されたクラスの集まりを クラスライブラリ と呼びます。

ドラゴンボールの世界観でたとえると、クラスライブラリは、悟空、ベジータ、ピッコロ、悟飯たちが任務で使えるように、戦士本部に最初から用意されている巨大な道具棚のようなものです。

そこには、戦士名簿、修行記録、通信装置、計算用スカウター、日付管理の巻物、画面表示の道具、画像処理の装置など、さまざまな用途の道具が並んでいます。

ただし、これらの道具が全部ひとつの棚に雑然と置かれているわけではありません。
Javaのクラスライブラリは、役割ごとに パッケージ で整理されています。

たとえば、基本的なクラスは java.lang、入出力関連は java.io、ネットワーク関連は java.net、便利な道具類は java.util というように分類されています。

Javaの考え方ドラゴンボール風のイメージ
クラスライブラリ悟空たちが使える巨大な戦士本部の道具棚
クラス1つひとつの巻物や道具
パッケージ用途ごとに分けられた棚
import別の棚の道具を使うための案内札

これまで学んできた package 文、import 文、パッケージ名.クラス名 という考え方は、自分で作ったクラスだけに関係するものではありません。

Javaが用意しているクラスライブラリを使うときにも、同じようにパッケージの考え方が使われます。

つまり、クラスライブラリを使いこなすには、
どのパッケージに、どんな役割のクラスが入っているのか
を意識することが大切です。

クラスライブラリとは何か

クラスライブラリとは、Javaがあらかじめ用意している便利なクラスの集まりです。

プログラムを書くとき、すべての機能を自分で作る必要はありません。

たとえば、文字列を扱う処理、ファイルを読む処理、日付を扱う処理、ネットワーク通信を行う処理などは、多くのプログラムで必要になります。

そのたびに全部を自作していたら、とても大変です。

そこで Java には、よく使う機能がクラスとしてあらかじめ用意されています。

やりたいこと使われるクラスやパッケージの例
文字列を扱うString
数学的な計算をするMath
ファイルを読み書きするjava.io
リストや便利な道具を使うjava.util
ネットワーク通信をするjava.net
大きな数値を正確に扱うjava.math

ドラゴンボール風にたとえると、悟空が任務のたびに毎回スカウターや通信装置、戦闘記録帳、修行メニュー表を自作するのではなく、戦士本部に用意された道具を借りて使うようなものです。

Javaのクラスライブラリを使うことで、プログラムを効率よく作れるようになります。

クラスライブラリのクラスもパッケージで整理されている

クラスライブラリには、非常に多くのクラスがあります。

もしそれらが全部同じ場所に置かれていたら、必要なクラスを探すだけでも大変です。

そこで Java では、標準クラスライブラリのクラスも、用途ごとにパッケージへ分類されています。

パッケージ名主な役割
java.langJavaの基本的なクラス
java.io入出力関連のクラス
java.netネットワーク関連のクラス
java.util便利な補助機能やコレクション関連のクラス
java.math高精度な数値計算に関するクラス
java.text数値や日付などの表示形式、国際化関連のクラス
java.awtウィンドウ部品関連のクラス
java.awt.eventイベント処理関連のクラス
java.awt.image画像処理関連のクラス

このように、パッケージ名を見るだけでも、だいたいどんな役割のクラスが含まれているのかが分かります。

ドラゴンボール風に言えば、戦士本部の道具棚が次のように分類されているイメージです。

Javaのパッケージドラゴンボール風の棚
java.lang悟空たちが常に使う基本任務の共通道具棚
java.ioブルマが記録を読み書きするための巻物棚
java.net界王さまや遠方の仲間と通信するための棚
java.util亀仙人の便利道具棚
java.mathスカウターで精密な戦闘力計算を行う算術棚
java.awt画面や表示部品の道具棚
java.awt.event操作や反応を扱う巻物棚
java.awt.image画像を扱う処理棚

パッケージは、ただクラスを入れる入れ物ではありません。
クラスの役割を整理し、必要な機能を探しやすくするための大切なしくみです。

パッケージで整理されていると何が便利なのか

クラスライブラリがパッケージで整理されていると、必要なクラスを探しやすくなります。

たとえば、ファイルの読み書きをしたいなら java.io を見る、便利なリストや日付関連の機能を使いたいなら java.util を見る、というように目的別に探せます。

状態困ること・便利なこと
パッケージ整理がない場合すべてのクラスが同じ場所に集まり、探しにくい
パッケージ整理がある場合用途ごとに分かれているため、目的のクラスを探しやすい

さらに、パッケージは同じ名前のクラスを区別するためにも役立ちます。

たとえば、同じ名前のクラスが複数あっても、パッケージが違えば別のクラスとして扱えます。

指定意味
pa.GokuWarriorpa パッケージの GokuWarrior
pc.GokuWarriorpc パッケージの GokuWarrior
java.awt.Listjava.awt パッケージの List
java.util.Listjava.util パッケージの List

ドラゴンボール風にたとえると、同じ GokuWarrior という名前の巻物があっても、置かれている棚が違えば取り違えを防げます。

名前だけを見るのではなく、どの棚にあるのかまで含めて管理する。
これがパッケージの大きな役割です。

図:クラスライブラリはパッケージで整理されている

この図が示していること

この図では、Javaのクラスライブラリが用途ごとのパッケージで整理されている様子を表しています。

中央の Java クラスライブラリ は、Javaが最初から用意している便利なクラスの集まりです。

その中には、java.lang、java.io、java.util、java.net、java.math、java.awt などの棚があります。

パッケージ役割
java.lang基本的なクラス
java.io入出力関連
java.util便利機能関連
java.netネットワーク関連
java.math数値計算関連
java.awt画面部品関連

この図から分かることは、クラスライブラリはただ大量のクラスを集めたものではなく、用途ごとにパッケージで整理されているということです。

クラスライブラリを使うときもimportが基本

別パッケージのクラスを使うときは、import を使うのが基本です。

これは、自分で作ったクラスを使う場合だけでなく、Javaのクラスライブラリを使う場合も同じです。

たとえば、java.io パッケージにある BufferedReader クラスを使いたいとします。

その場合、ソースファイルの先頭付近に次のように書きます。

import java.io.BufferedReader;

これにより、プログラムの中では BufferedReader と短く書けます。

import を使わない場合は、次のように完全な名前で書く必要があります。

java.io.BufferedReader

比較すると、次のようになります。

書き方特徴
java.io.BufferedReaderどのパッケージのクラスか明確だが長い
import java.io.BufferedReader; を書いて BufferedReader短く書けて読みやすい

ドラゴンボール風にたとえると、毎回 java.io の棚にある BufferedReader の巻物 と言うのは長いです。

そこで、任務開始前に import java.io.BufferedReader; と案内札を出しておきます。
そうすれば、任務中は BufferedReader と短く呼べるようになります。

なぜimportが必要になるのか

Javaのクラスライブラリには、多くのクラスがあります。

それらはパッケージごとに分類されているため、別パッケージのクラスを使うときには、どこにあるクラスなのかをJavaに伝える必要があります。

BufferedReader は java.io パッケージにあります。

そのため、何も準備しない場合は、次のように完全な名前で指定する必要があります。

java.io.BufferedReader

しかし、何度もこの形を書くと、コードが長くなりやすいです。

そこで import を使います。

import java.io.BufferedReader;

これを書いておけば、以降は BufferedReader と短く書けます。

考え方内容
パッケージ名.クラス名クラスの完全な住所を示す
importそのクラスを短い名前で使えるようにする
クラス名だけimport 後に使いやすくなる短い表記

import は、クラスの所属を変えるものではありません。

BufferedReader は、import しても java.io パッケージのクラスのままです。
import は、あくまで今書いているファイルの中で使いやすくするための宣言です。

java.langだけは特別

ここで大切な例外があります。

それが java.lang パッケージ です。

java.lang に含まれるクラスは、通常 import を書かなくても使えます。

たとえば、String や Math は、これまで特別な import を書かずに使ってきたはずです。

String name = "悟空";

int max = Math.max(10, 20);

本来、String は java.lang.String、Math は java.lang.Math です。

しかし、java.lang はJavaの基本的なクラスを含む特別なパッケージなので、自動的に使えるようになっています。

クラス本来の完全名import
Stringjava.lang.String通常不要
Mathjava.lang.Math通常不要
Systemjava.lang.System通常不要

この点を整理すると、次のようになります。

パッケージimport の必要性
java.lang通常不要
java.lang 以外基本的に必要

ドラゴンボール風にたとえると、java.lang は悟空やベジータが常に身につけている基本装備のようなものです。

任務のたびに申請しなくても、最初から使える状態になっています。

String を import なしで使えるのは、String が特別な文法だからではありません。
String が java.lang に属しており、java.lang が自動的に使えるパッケージだからです。

同じパッケージの複数クラスをimportするとき

同じパッケージから複数のクラスを使いたい場合、1つずつ import することもできます。

たとえば、java.io の BufferedReader と IOException を使う場合です。

import java.io.BufferedReader;
import java.io.IOException;

この書き方は正しいです。

使うクラスが少ない場合は、どのクラスを使っているのかが明確で分かりやすいです。

import 文意味
import java.io.BufferedReader;BufferedReader を使う
import java.io.IOException;IOException を使う

ただし、同じパッケージからたくさんのクラスを使う場合、import 文が何行も並びます。

ドラゴンボール風にたとえると、java.io の棚から複数の巻物を使いたいのに、1本ずつ申請書を書いているようなものです。

そのようなときに便利なのが、アスタリスクを使った import です。

アスタリスクを使ったimport

同じパッケージの複数クラスをまとめて使いたい場合は、アスタリスクを使えます。

import java.io.*;

このように書くと、java.io パッケージに含まれるクラスを使いやすくなります。

書き方意味
import java.io.BufferedReader;BufferedReader だけを指定する
import java.io.IOException;IOException だけを指定する
import java.io.*;java.io パッケージ内のクラスをまとめて使いやすくする

アスタリスクを使うと、同じパッケージのクラスを複数使うときに、import 文を短くできます。

ただし、アスタリスクは何でもまとめて読み込む魔法ではありません。

重要なのは、指定したパッケージの直下のクラスだけが対象 という点です。

アスタリスクではサブパッケージまで含まれない

ここはとても大切です。

import java.awt.*; と書いた場合、使いやすくなるのは java.awt パッケージに含まれるクラスです。

しかし、java.awt.image パッケージのクラスまでは含まれません。

import java.awt.*;

この書き方では、java.awt.image のクラスは対象外です。

java.awt.image のクラスも使いたい場合は、別に次のような import が必要です。

import java.awt.image.*;

表で整理すると、次のようになります。

import 文利用しやすくなる範囲
import java.awt.*;java.awt パッケージのクラス
import java.awt.image.*;java.awt.image パッケージのクラス
import java.awt.*; だけjava.awt.image までは含まれない

これは、サブパッケージが別パッケージとして扱われるからです。

以前学んだ pa と pa.sub の関係と同じです。

パッケージJavaでの扱い
papa パッケージ
pa.subpa.sub パッケージ
java.awtjava.awt パッケージ
java.awt.imagejava.awt.image パッケージ

名前がつながっていても、Javaでは別々のパッケージです。

ドラゴンボール風にたとえると、java.awt の棚をまとめて使う申請をしても、その中の別管理区画である java.awt.image の棚までは自動では使えない、ということです。

図:importとアスタリスクの範囲

この図が示していること

この図では、アスタリスクを使った import の範囲を表しています。

左側の java.awt には、Button、Frame、Graphics などのクラスがあります。
import java.awt.*; と書くと、java.awt パッケージ内のクラスを使いやすくできます。

一方、右側の java.awt.image は、java.awt の下に見える名前ですが、Javaでは別パッケージとして扱われます。

そのため、java.awt.image のクラスを使いたい場合は、別に import java.awt.image.*; が必要です。

import 文対象
import java.awt.*;java.awt のクラス
import java.awt.image.*;java.awt.image のクラス
import java.awt.*; だけjava.awt.image は含まれない

この図から分かることは、アスタリスクは指定したパッケージ直下のクラスだけを対象にし、サブパッケージまでは含まないということです。

サンプルプログラム

ここでは、java.util パッケージの ArrayList と Random を使うサンプルプログラムを見てみます。

ArrayList は複数のデータを管理するためのクラスです。
Random はランダムな値を作るためのクラスです。

ドラゴンボール風に考えると、ArrayList は戦士名簿、Random は出撃戦士をランダムに選ぶスカウターのような役割です。

ファイル名:LibraryDemo.java

import java.util.ArrayList;
import java.util.Random;

class LibraryDemo
{
    public static void main(String[] args)
    {
        ArrayList<String> warriors = new ArrayList<String>();

        warriors.add("悟空");
        warriors.add("ベジータ");
        warriors.add("ピッコロ");
        warriors.add("悟飯");
        warriors.add("クリリン");

        Random random = new Random();
        int index = random.nextInt(warriors.size());

        String selectedWarrior = warriors.get(index);

        System.out.println("戦士名簿:" + warriors);
        System.out.println("今回の出撃戦士は" + selectedWarrior + "です。");

        int maxPower = Math.max(8000, 12000);
        System.out.println("比較した最大戦闘力は" + maxPower + "です。");
    }
}

実行結果の例

Random を使っているため、出撃戦士の表示は実行するたびに変わる可能性があります。

戦士名簿:[悟空, ベジータ, ピッコロ, 悟飯, クリリン]
今回の出撃戦士はベジータです。
比較した最大戦闘力は12000です。

サンプルプログラムで使っているクラスライブラリ

このプログラムでは、Javaが用意しているクラスライブラリを使っています。

import java.util.ArrayList;
import java.util.Random;

ArrayList と Random は、どちらも java.util パッケージにあるクラスです。

そのため、ファイルの先頭で import しています。

クラス所属パッケージ役割
ArrayListjava.util複数のデータをリストとして管理する
Randomjava.utilランダムな値を作る
Mathjava.lang数学的な計算をする
Systemjava.lang標準出力などを扱う
Stringjava.lang文字列を扱う

ここで注目したいのは、Math、System、String には import を書いていないことです。

String selectedWarrior = warriors.get(index);

int maxPower = Math.max(8000, 12000);

System.out.println("比較した最大戦闘力は" + maxPower + "です。");

String、Math、System は java.lang パッケージにあります。
java.lang は自動的に使えるため、import を書かなくても利用できます。

import が必要なものimport が不要なもの
java.util.ArrayListjava.lang.String
java.util.Randomjava.lang.Math
java.io.BufferedReaderjava.lang.System

ドラゴンボール風にたとえると、ArrayList や Random は本部の便利道具棚から借りる道具です。
そのため、import という案内札を出します。

一方、String、Math、System は悟空たちが最初から持っている基本装備のようなもので、最初から使える状態になっています。

クラスライブラリのパッケージをドラゴンボール風に整理する

Javaのクラスライブラリを、戦士本部の資料棚として見ると、次のように整理できます。

パッケージ戦士本部の棚のイメージ使う場面
java.lang基本道具棚String、Math、System など基本機能
java.io記録入出力棚ファイルや文字の読み書き
java.net遠方通信棚ネットワーク通信
java.util便利道具棚リスト、日付、補助機能
java.math精密計算棚大きな数値や正確な計算
java.text表示形式棚日付や数値の表示調整
java.awt画面部品棚ウィンドウや部品
java.awt.event操作反応棚ボタン操作やイベント
java.awt.image画像処理棚画像関連の処理

こうして見ると、Javaの標準クラスライブラリは、ただ大量のクラスが集まっているだけではないことが分かります。

用途ごとに棚が分かれているため、必要な機能を探しやすくなっています。

モジュールという上位の考え方

Java 9以降では、パッケージよりさらに大きな単位として モジュール という考え方があります。

パッケージは、クラスを整理する単位です。
一方、モジュールは、パッケージのまとまりをさらに管理する単位です。

単位役割
クラス実際の処理を持つ部品
パッケージクラスを用途ごとに整理する単位
モジュールパッケージ群の公開範囲や依存関係を管理する単位

ドラゴンボール風にたとえると、クラスは1本の巻物です。
パッケージは巻物を整理する棚です。
モジュールは、複数の棚をまとめた部署や管理区画です。

たとえば、ある部署では、外部に見せてよい棚と、内部だけで使う棚を分けたいことがあります。

モジュールを使うと、次のようなことを管理できます。

モジュールで考えること内容
どのパッケージを外部に公開するか使ってよい機能を明確にする
どのパッケージを内部だけで使うか内部処理を隠す
どのモジュールがどのモジュールを使うか依存関係を整理する

モジュールを定義するときは、module-info.java というファイルを使います。

ただし、Java学習の初期段階では、まずパッケージと import をしっかり理解することが大切です。

モジュールは、より大きな構成を扱うときに登場する上位の整理単位だと考えるとよいです。

標準クラスライブラリとモジュール

Java 9以降では、標準クラスライブラリもモジュール単位で整理されています。

たとえば、基本的なクラス群は java.base というモジュールに含まれています。

java.base には、java.lang など、Javaの基本的な機能が含まれます。

モジュール含まれるものの例
java.baseJavaの基本的な機能
java.desktopAWTやSwingなど、画面関連の機能
java.sqlデータベース関連の機能

普段の学習では、モジュール名を強く意識しなくても使える場面が多いです。

しかし、大きなアプリケーションやライブラリを扱うようになると、どのモジュールが必要なのかを指定する場面があります。

ドラゴンボール風に言うと、最初は本部の道具棚を使うだけで十分です。
しかし、大きな任務部隊を組むようになると、どの部署の棚を外部に公開するか、どの部署がどの部署を利用するかまで管理する必要が出てくる、というイメージです。

名前のないモジュール

モジュールを明示していない通常の学習用プログラムは、名前のないモジュールに属するものとして扱われます。

つまり、最初から module-info.java を書かなくても、Javaの学習や小さなプログラムの実行はできます。

状態扱い
module-info.java がない名前のないモジュールに属する
module-info.java がある名前のあるモジュールとして扱う

この仕組みがあるため、初心者の段階では、モジュールを強く意識しなくてもJavaを学べます。

まずは、クラス、パッケージ、import の関係を理解する。
その上で、必要になったらモジュールという上位のしくみに進む、という流れで十分です。

図:クラス・パッケージ・モジュールの関係

この図が示していること

この図では、クラス、パッケージ、モジュールの関係を表しています。

クラスは、実際の処理を持つ部品です。
String、Math、ArrayList、BufferedReader のような1つひとつの便利な部品がクラスです。

パッケージは、それらのクラスを用途ごとに整理する棚です。
java.lang、java.util、java.io、java.awt のように、役割ごとに分類されています。

モジュールは、パッケージ群をさらに大きく管理する単位です。
java.base や java.desktop のように、複数のパッケージをまとめ、公開範囲や依存関係を管理します。

単位役割
クラス実際の処理を持つ部品
パッケージクラスを用途ごとに整理する
モジュールパッケージ群を大きく管理する

この図から分かることは、Javaの標準クラスライブラリは、クラス、パッケージ、モジュールという段階で整理されているということです。

クラスライブラリを使いこなすために大切な視点

Javaの学習では、自分でクラスを作れるようになることも大切です。

しかし、それと同じくらい大切なのが、Javaが用意しているクラスライブラリを上手に使うことです。

そのためには、どのパッケージに何があるのかを意識できるようになる必要があります。

やりたいこと見るとよいパッケージ
基本的なクラスを使うjava.lang
ファイルや文字を読み書きするjava.io
ネットワークを扱うjava.net
リストや便利な補助機能を使うjava.util
正確な数値計算をするjava.math
表示形式を整えるjava.text
画面部品を扱うjava.awt
イベントを扱うjava.awt.event
画像を扱うjava.awt.image

この視点があると、必要なクラスを探しやすくなります。

また、import の意味が分かっていれば、別パッケージのクラスも自然に使えるようになります。

クラスライブラリとパッケージで押さえておきたいこと

クラスライブラリとパッケージの関係では、次の点を押さえておくと理解しやすくなります。

大切なポイント内容
クラスライブラリJavaがあらかじめ用意しているクラスの集まり
パッケージクラスを役割ごとに整理するしくみ
標準クラスもパッケージで整理されるjava.lang、java.io、java.util など
import別パッケージのクラスを短く使いやすくする
java.lang通常 import 不要
import パッケージ名.*;同じパッケージ直下の複数クラスを使いやすくする
サブパッケージ* では自動的に含まれない
モジュールパッケージ群をさらに大きく管理する単位

Javaのクラスライブラリは、ただ便利なクラスがたくさん置かれているだけではありません。

役割ごとにパッケージへ整理され、必要に応じて import して使えるようになっています。

ドラゴンボール風に言えば、Javaの標準クラスライブラリは、悟空、ベジータ、ピッコロ、悟飯たちが任務で使う巻物や道具が分類された巨大な戦士本部資料庫です。

どの棚にどんな巻物があるのかを知り、必要なものを import して使えるようになると、Javaの便利な機能をもっと自然に使いこなせるようになります。